import {
  pgClients, getTemplate, handlebars, metaFormat,
} from '@opengis/fastify-table/utils.js';

export default async function mapFormat(req, reply) {
  const { pg = pgClients.client, query = {}, user } = req;
  const { layer, id } = query;
  const time = Date.now();

  if (!layer || !id) return reply.status(404).send('not enough params: layer,id,map is required');

  const service = await getTemplate('layer', layer) || (pg.tlist.includes('gis.services') ? await pg.query('SELECT * FROM gis.services WHERE service_id = $1', [layer]).then(res => res.rows[0]) : null);

  const {
    source_path: tname, cardInterface, card, template,
  } = service;

  const columns = (card || []).filter((col) => (user?.uid ? true : !col.is_admin));
  if (!tname) return reply.status(404).send('missing source_path');

  const pk = pg.pk?.[tname];
  if (!pk) return reply.status(404).send('missing pk');

  if (!columns) return reply.status(404).send('columns setting not found');

  const columnNames = columns.map(col => col.name);
  const excluded = ['created_by', 'created_at', 'updated_by', 'geom', 'id', 'uid', 'updated_at', 'cdate', 'editor_date', 'editor_id'];
  const filteredColumns = columnNames.filter(name => !excluded.includes(name));

  const rows = await pg.query(
    `SELECT ${pk} as "id", geom::json, geom::box2d as box2d ${filteredColumns?.length > 0 ? ',' : ''}  ${filteredColumns.map((n) => `"${n}"`).join(', ')} FROM ${tname} WHERE ${pk} = $1`,
    [id],
  ).then(el => el.rows || []);

  if (!rows.length) return reply.status(404).send('object not found');

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

  rows.forEach(row => Object.assign(row, { box2d: undefined, bounds: row.box2d ? row.box2d.replace(/[A-Z\)\(]+/g, '').split(/[ ,]+/).map(el => el - 0) : null }));

  await metaFormat({
    rows, table: tname, cls: classifiers, sufix: false,
  });
  const fullRow = rows[0];

  const result = [];
  const filtered = columns.filter(col => !excluded.includes(col.name));
  for (let i = 0; i < filtered.length; i += 1) {
    const col = filtered[i];

    const name = col.label || col.ua || col.name;
    const value = (col.format === 'date' ? new Date(fullRow[col.name]).toLocaleDateString('uk-UA') : null) || fullRow[`${col.name}_data`]?.text
      || fullRow[`${col.name}_text`]
      || fullRow[col.name];

    result.push(`<div class="grid grid-cols-1 gap-1 py-3 sm:grid-cols-3 sm:gap-4 even:bg-gray-50 text-[12px]">
            <dt class="text-gray-900">${name}</dt>
            <dd class="text-gray-700 sm:col-span-2">${value || '-'}</dd>
        </div>`);
  }

  const htmlTemplate = pg?.pk?.['admin.templates'] && service.card_mode === 'html'
    ? await pg.query('select body from admin.templates where name=$1 limit 1', [template || layer]).then(el => el.rows?.[0]?.body)
    : null;

  const html1 = htmlTemplate ? await handlebars.compile(htmlTemplate)(fullRow) : null;

  const html = html1 || `<dl class="divide-y divide-gray-100 py-[5px]">${result.join('')}</dl>`;

  const res = {
    time: Date.now() - time,
    id,
    rows: fullRow,
    columns,
    template,
    html,
  };
  if (service) {
    res.cardInterface = cardInterface;
  }

  return res;
}
