import { pool } from "../db/pool.js";
import { ApiError } from "../utils/ApiError.js";

const cleanString = (value) => String(value ?? "").trim();

const toLikePattern = (value) => `%${value.replace(/\s+/g, "%")}%`;

export const searchController = {
  search: async (req, res) => {
    const companyId = Number(req.query.company_id || req.user?.companyId || 0);
    const query = cleanString(req.query.q);
    const limit = Math.min(Math.max(Number.parseInt(req.query.limit, 10) || 5, 1), 20);

    if (!companyId) {
      throw new ApiError(400, "company_id is required.");
    }

    if (query.length < 2) {
      res.json({
        query,
        groups: {
          accounts: [],
          clients: [],
          suppliers: [],
          entries: [],
        },
      });
      return;
    }

    const pattern = toLikePattern(query);

    const [accountsResponse, clientsResponse, suppliersResponse, entriesResponse] =
      await Promise.all([
        pool.query(
          `
            SELECT id, code, label
            FROM accounts
            WHERE company_id = $1
              AND is_active = TRUE
              AND (
                code ILIKE $2
                OR label ILIKE $2
              )
            ORDER BY code ASC
            LIMIT $3
          `,
          [companyId, pattern, limit],
        ),
        pool.query(
          `
            SELECT id, ref_code, name
            FROM auxiliary_accounts
            WHERE company_id = $1
              AND third_party_type = 'client'
              AND (
                ref_code ILIKE $2
                OR name ILIKE $2
              )
            ORDER BY name ASC
            LIMIT $3
          `,
          [companyId, pattern, limit],
        ),
        pool.query(
          `
            SELECT id, ref_code, name
            FROM auxiliary_accounts
            WHERE company_id = $1
              AND third_party_type = 'supplier'
              AND (
                ref_code ILIKE $2
                OR name ILIKE $2
              )
            ORDER BY name ASC
            LIMIT $3
          `,
          [companyId, pattern, limit],
        ),
        pool.query(
          `
            SELECT
              je.id,
              je.piece_ref,
              je.label,
              TO_CHAR(je.entry_date, 'YYYY-MM-DD') AS entry_date,
              j.code AS journal_code
            FROM journal_entries je
            JOIN journals j
              ON j.id = je.journal_id
            WHERE je.company_id = $1
              AND (
                COALESCE(je.piece_ref, '') ILIKE $2
                OR je.label ILIKE $2
              )
            ORDER BY je.entry_date DESC, je.id DESC
            LIMIT $3
          `,
          [companyId, pattern, limit],
        ),
      ]);

    res.json({
      query,
      groups: {
        accounts: accountsResponse.rows.map((row) => ({
          id: Number(row.id),
          type: "account",
          title: `${row.code} · ${row.label}`,
          subtitle: row.label,
          route: "/accounts",
        })),
        clients: clientsResponse.rows.map((row) => ({
          id: Number(row.id),
          type: "client",
          title: `${row.ref_code} · ${row.name}`,
          subtitle: row.name,
          route: `/clients/${row.id}/edit`,
        })),
        suppliers: suppliersResponse.rows.map((row) => ({
          id: Number(row.id),
          type: "supplier",
          title: `${row.ref_code} · ${row.name}`,
          subtitle: row.name,
          route: `/suppliers/${row.id}/edit`,
        })),
        entries: entriesResponse.rows.map((row) => ({
          id: Number(row.id),
          type: "entry",
          title: `${row.piece_ref || "Pièce"} · ${row.label}`,
          subtitle: `${row.journal_code} · ${row.entry_date}`,
          route: `/entries/${row.id}`,
        })),
      },
    });
  },
};
