import type { Pool } from 'pg';

export interface DocumentoExtra {
  id: number;
  contribuyenteId: string | null;
  nombre: string;
  descripcion: string | null;
  categoria: string | null;
  pdfFilename: string;
  subidoPor: string | null;
  createdAt: string;
}

interface CreateExtraInput {
  contribuyenteId?: string | null;
  nombre: string;
  descripcion?: string | null;
  categoria?: string | null;
  pdfBase64: string;
  pdfFilename: string;
  subidoPor: string;
}

function sanitizeUuid(id: string): string {
  return id.replace(/[^a-f0-9-]/gi, '');
}

export async function createExtra(
  pool: Pool,
  data: CreateExtraInput,
): Promise<DocumentoExtra> {
  const pdfBuffer = Buffer.from(data.pdfBase64, 'base64');
  const contribuyenteId = data.contribuyenteId
    ? sanitizeUuid(data.contribuyenteId)
    : null;
  const { rows } = await pool.query(
    `INSERT INTO documentos_extras
       (contribuyente_id, nombre, descripcion, categoria, pdf, pdf_filename, subido_por)
     VALUES ($1, $2, $3, $4, $5, $6, $7)
     RETURNING id, contribuyente_id AS "contribuyenteId", nombre, descripcion,
               categoria, pdf_filename AS "pdfFilename", subido_por AS "subidoPor",
               created_at AS "createdAt"`,
    [
      contribuyenteId,
      data.nombre,
      data.descripcion ?? null,
      data.categoria ?? null,
      pdfBuffer,
      data.pdfFilename,
      data.subidoPor,
    ],
  );
  const r = rows[0];
  return { ...r, createdAt: r.createdAt?.toISOString?.() ?? r.createdAt };
}

export async function listExtras(
  pool: Pool,
  contribuyenteId?: string | null,
  categoria?: string | null,
): Promise<DocumentoExtra[]> {
  const params: any[] = [];
  const where: string[] = [];
  if (contribuyenteId) {
    params.push(sanitizeUuid(contribuyenteId));
    where.push(`contribuyente_id = $${params.length}`);
  }
  if (categoria) {
    params.push(categoria);
    where.push(`categoria = $${params.length}`);
  }
  const whereClause = where.length ? `WHERE ${where.join(' AND ')}` : '';
  const { rows } = await pool.query(
    `SELECT id, contribuyente_id AS "contribuyenteId", nombre, descripcion,
            categoria, pdf_filename AS "pdfFilename", subido_por AS "subidoPor",
            created_at AS "createdAt"
     FROM documentos_extras
     ${whereClause}
     ORDER BY created_at DESC
     LIMIT 500`,
    params,
  );
  return rows.map((r: any) => ({
    ...r,
    createdAt: r.createdAt?.toISOString?.() ?? r.createdAt,
  }));
}

export async function getExtraPdf(
  pool: Pool,
  id: number,
): Promise<{ buffer: Buffer; filename: string; nombre: string } | null> {
  const { rows } = await pool.query(
    `SELECT pdf, pdf_filename AS "pdfFilename", nombre
     FROM documentos_extras WHERE id = $1`,
    [id],
  );
  if (rows.length === 0) return null;
  return {
    buffer: rows[0].pdf,
    filename: rows[0].pdfFilename,
    nombre: rows[0].nombre,
  };
}

export async function deleteExtra(pool: Pool, id: number): Promise<boolean> {
  const { rowCount } = await pool.query(
    `DELETE FROM documentos_extras WHERE id = $1`,
    [id],
  );
  return (rowCount ?? 0) > 0;
}

export async function listCategorias(
  pool: Pool,
  contribuyenteId?: string | null,
): Promise<string[]> {
  const params: any[] = [];
  let where = `WHERE categoria IS NOT NULL AND categoria != ''`;
  if (contribuyenteId) {
    params.push(sanitizeUuid(contribuyenteId));
    where += ` AND contribuyente_id = $${params.length}`;
  }
  const { rows } = await pool.query(
    `SELECT DISTINCT categoria FROM documentos_extras ${where} ORDER BY categoria`,
    params,
  );
  return rows.map((r: any) => r.categoria);
}
