import type { Request, Response, NextFunction } from 'express';
import { prisma } from '../config/database.js';

export async function getFormasPago(req: Request, res: Response, next: NextFunction) {
  try {
    const data = await prisma.catFormaPago.findMany({ orderBy: { clave: 'asc' } });
    res.json(data);
  } catch (error) { next(error); }
}

export async function getMetodosPago(req: Request, res: Response, next: NextFunction) {
  try {
    const data = await prisma.catMetodoPago.findMany({ orderBy: { clave: 'asc' } });
    res.json(data);
  } catch (error) { next(error); }
}

export async function getUsosCfdi(req: Request, res: Response, next: NextFunction) {
  try {
    const data = await prisma.catUsoCfdi.findMany({ orderBy: { clave: 'asc' } });
    res.json(data);
  } catch (error) { next(error); }
}

export async function getMonedas(req: Request, res: Response, next: NextFunction) {
  try {
    const data = await prisma.catMoneda.findMany({ orderBy: { clave: 'asc' } });
    res.json(data);
  } catch (error) { next(error); }
}

export async function getClavesUnidad(req: Request, res: Response, next: NextFunction) {
  try {
    const data = await prisma.catClaveUnidad.findMany({ orderBy: { descripcion: 'asc' } });
    res.json(data);
  } catch (error) { next(error); }
}

export async function searchClaveProdServ(req: Request, res: Response, next: NextFunction) {
  try {
    const q = (req.query.q as string || '').trim();
    if (q.length < 2) {
      return res.json([]);
    }

    // Buscar por clave o descripción
    // Primero buscar por clave, luego por texto
    const data = await prisma.catClaveProdServ.findMany({
      where: {
        OR: [
          { clave: { startsWith: q } },
          { descripcion: { contains: q, mode: 'insensitive' } },
        ],
      },
      take: 20,
      orderBy: { clave: 'asc' },
    });

    // Si no hay resultados, intentar sin acentos
    if (data.length === 0) {
      const normalized = q.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
      if (normalized !== q) {
        const fallback = await prisma.catClaveProdServ.findMany({
          where: { descripcion: { contains: normalized, mode: 'insensitive' } },
          take: 20,
          orderBy: { clave: 'asc' },
        });
        return res.json(fallback);
      }

      // Buscar con variantes comunes de acentos
      const withAccents = normalized
        .replace(/a/gi, '[aá]').replace(/e/gi, '[eé]')
        .replace(/i/gi, '[ií]').replace(/o/gi, '[oó]').replace(/u/gi, '[uú]')
        .replace(/n/gi, '[nñ]');

      // Usar raw SQL con regex para búsqueda flexible
      const rows: any[] = await prisma.$queryRawUnsafe(
        `SELECT id, clave, descripcion FROM cat_clave_prod_serv WHERE descripcion ~* $1 ORDER BY clave LIMIT 20`,
        withAccents
      );
      return res.json(rows);
    }

    res.json(data);
  } catch (error) { next(error); }
}

export async function getObjetosImp(req: Request, res: Response, next: NextFunction) {
  try {
    const data = await prisma.catObjetoImp.findMany({ orderBy: { clave: 'asc' } });
    res.json(data);
  } catch (error) { next(error); }
}

export async function getTiposRelacion(req: Request, res: Response, next: NextFunction) {
  try {
    const data = await prisma.catTipoRelacion.findMany({ orderBy: { clave: 'asc' } });
    res.json(data);
  } catch (error) { next(error); }
}

export async function getExportaciones(req: Request, res: Response, next: NextFunction) {
  try {
    const data = await prisma.catExportacion.findMany({ orderBy: { clave: 'asc' } });
    res.json(data);
  } catch (error) { next(error); }
}
