import { getMeta, getFilterSQL, metaFormat } from "@opengis/fastify-table/utils.js";
import { populateFilterOptions } from './classifiers.js';
import { extractVisibleColumns } from './columns.js';

const columnType = {
  text: 'text',
  date: 'date',
  bool: 'yes/no',
  numeric: 'number',
  integer: 'number',
  'timestamp without time zone': 'date',
  'timestamp with time zone': 'date',
};

// eslint-disable-next-line import/prefer-default-export
export async function handleRegistryRequest({
  settings, query, object_id, offset = 0, limit = 16, page = 1, pg, sql,
}) {
  const {
    name, table_name, description, card, columns, filters, query: whereQuery, pk,
    register_id, view, order, is_downloadable, register_key, is_map, is_register, service_id, is_files,
  } = settings;
  const parsedColumns = Array.isArray(columns) ? columns : JSON.parse(columns);
  const filtersParsed = Array.isArray(filters) ? filters : JSON.parse(filters);
  const activeFilters = (filtersParsed || []).filter((f) => f.disabled !== true).map(el => ({
    ...el, id: el.name || el.id, type: el.type, api: `/api/suggest/${table_name}:${el.name}${el.data ? `?sel=${el.data}` : ''}`,
  }));
  const { columns: fields1, geom } = await getMeta({ pg, table: table_name });

  const fields = fields1?.map?.(({ name, dataTypeID, title }) => ({ name, type: columnType[pg.pgType?.[dataTypeID] || 'text'] || 'text', label: title || name }));

  const mode = object_id ? "card" : "table";
  const visibleColumns = parsedColumns ? extractVisibleColumns(parsedColumns, mode) : [];
  const selectColumns = visibleColumns.map((col) => col.name);
  /* const columnsInfo = visibleColumns.map((col) => ({
        name: col.name,
        ua: col.ua,
        format: col.format,
        data: col.data,
        view_type: col.view_type
    })); */

  const classifiers = visibleColumns
    .filter((col) => col.data && ["select", "badge", "tags"].includes(col.format))
    .reduce((acc, curr) => ({ ...acc, [curr.name]: curr.data }), {});

  if (object_id) {
    const sql = `
            SELECT "${pk}" as id,* ${selectColumns.length ? `, ${selectColumns.join(", ")}` : ''} ${geom ? `, st_asgeojson(${geom})::json as geom` : ''}
            FROM ${table_name}
            WHERE ${pk} = $1
        `;
    const rows = await pg.query(sql, [object_id]).then(el => el.rows || []);
    if (!rows.length) throw new Error('Object not found');

    await metaFormat({
      rows, table: table_name, cls: classifiers, sufix: true,
    });

    return {
      row: rows[0],
      card,
      d: 1,
      columns: visibleColumns,
      is_downloadable,
      register_key,
      register_id,
      service_id,
      name,
      is_files,
      is_map,
      is_register,
    };
  }

  const { search, filter } = query || {};
  const { q: sqlFilter } = (filter || search)
    ? await getFilterSQL({
      table: table_name,
      search,
      filter,
      filterList: activeFilters,
    })
    : { q: '1=1' };

  const whereConditions = [whereQuery, sqlFilter].filter(Boolean).join(' AND ');

  const sqlBase = `FROM ${table_name} WHERE ${whereConditions || 'true'}`;
  const sqlOrder = order ? `ORDER BY ${order}` : "";
  const sqlLimit = `LIMIT $1 OFFSET $2`;

  const sqlSelect = `SELECT "${pk}" as id ${selectColumns.length ? `, ${selectColumns.join(", ")}` : ''} ${geom ? `, st_asgeojson(${geom})::json as geom` : ''} ${sqlBase}`;
  const dataQuery = `${sqlSelect} ${sqlOrder} ${sqlLimit}`;

  if (sql) return dataQuery;

  const rows = await pg.query(dataQuery, [limit, offset]).then(el => el.rows || []);
  const total = await pg.query(`SELECT COUNT(*) ${sqlBase}`).then(el => +(el.rows[0]?.count || 0));

  await metaFormat({
    rows, table: table_name, cls: classifiers, sufix: true,
  });

  const listConfig = {};

  if (parsedColumns?.length) {
    for (const col of parsedColumns) {
      if (col.view_type === 'title') listConfig.title = col.name;
      if (col.view_type === 'subtitle') listConfig.subtitle = col.name;
    }
  }

  await populateFilterOptions({
    pg,
    table: table_name,
    filters: activeFilters,
    columns,
    whereConditions,
  });

  return {
    register_id,
    name,
    card,
    table_name,
    register_key,
    description,
    rows,
    total,
    service_id,
    columns: visibleColumns,
    filters: activeFilters,
    fields,
    limit,
    page,
    view,
    is_downloadable,
    is_map,
    is_register,
    is_files,
    config: {
      listConfig,
    },
  };
}
