import { readFile } from 'node:fs/promises';
import { getTemplatePath, pgClients } from '@opengis/fastify-table/utils.js';

export default async function userCls(req) {
  const {
    pg = pgClients.client, params = {}, query = {}, user = {},
  } = req;
  const { uid } = user || {};

  if (!uid) {
    return { message: 'access restricted', status: 403 };
  }

  if (query.type && !['json', 'sql'].includes(query.type)) {
    return { message: 'param type is invalid', status: 400 };
  }

  const q = `select user_clsid as id, name, type, 
  case when type='json' then (
      ${params?.id
      ? `(with recursive rows as (
        select user_clsid, code as id, name as text, icon, color, parent
        from admin.user_cls a
        where name=u.name
        union all
        select a.user_clsid, a.code, a.name, a.icon, a.color, a.parent
        from admin.user_cls a
        join rows b on a.parent=b.text
      ) select json_agg(row_to_json(q)) from rows q where text<>u.name
     )`
      : 'select count(*)::int from admin.user_cls where parent=u.name'} ) else null end as children, 
      case when type='sql' then data else null end as sql from admin.user_cls u
    where (case when type='json' then parent is null else true end)
    and uid=(select uid from admin.users where $1 in (login,uid) limit 1)
    and parent is null and ${query.type ? `type='${query.type}'` : '1=1'} and ${params?.id ? 'u.name=$2' : '1=1'}
    order by cdate desc`;

  if (query?.sql) return q;


  const { rows = [] } = await pg.query(q, [uid, params.id].filter((el) => el));

  rows.forEach((row) => {
    if (row.type === 'sql') delete row.children;
    if (row.type === 'json') { delete row.sql; Object.assign(row, { children: row.children || (params?.id ? [] : 0) }); }
  });

  const clsList = query.type === 'sql' ? [] : getTemplatePath('cls'); // skip cls if type sql
  const selectList = query.type === 'json' ? [] : getTemplatePath('select'); // skip sql if type json

  const userClsNames = rows.map((el) => el.name);
  const selectNames = selectList.map((el) => el[0]);

  const arr = (clsList || []).concat(selectList || []).map((el) => ({ name: el[0], path: el[1], type: el[2] }))
    ?.filter((el) => (params?.id ? el.name === params?.id : true))
    ?.filter((el) => ['sql', 'json'].includes(el?.type) && !userClsNames.includes(el.name))
    ?.filter((el) => (el?.type === 'json' ? !selectNames?.includes(el?.name) : true));

  const res = await Promise.all(arr?.map(async (el) => {
    const type = { json: 'cls', sql: 'select' }[el.type] || el.type;
    // const clsData = await getSelect(type, el.name);
    const str = await readFile(el.path, 'utf-8');
    const clsData = type === 'cls' ? JSON.parse(str) : str;
    if (type === 'cls') {
      const children = params?.id ? clsData : clsData?.length || 0;
      return { name: el.name, type: el.type, children };
    }
    return { name: el.name, type: el.type, sql: clsData?.sql || clsData };
  }));

  return { message: { rows: rows.concat(res) }, status: 200 };
}
