import type { Context } from "hono";
import { prisma } from "../../../lib/prisma";
import { logger } from "../../../lib/logger";
import { PaymentStatus } from "../../../generated/prisma/client";

function parseAmount(raw: string): number | null {
  const cleaned = raw.replace("$", "").replace(/,/g, "").trim();
  if (!cleaned) return null;
  const n = Number(cleaned);
  return isNaN(n) ? null : n;
}

function parseDate(raw: string): Date | null {
  const trimmed = raw.trim();
  if (!trimmed) return null;
  const d = new Date(trimmed);
  return isNaN(d.getTime()) ? null : d;
}

export async function importExpensesHandler(c: Context) {
  const body = await c.req.parseBody();
  const file = body["file"];

  if (!file || !(file instanceof File)) {
    return c.json({ error: "No se envió ningún archivo" }, 400);
  }

  const text = await file.text();
  const lines = text.trim().split("\n");

  if (lines.length < 2) {
    return c.json({ error: "El archivo está vacío o solo tiene encabezados" }, 400);
  }

  let imported = 0;
  let skipped = 0;
  const errors: string[] = [];

  for (let i = 1; i < lines.length; i++) {
    const line = lines[i].trim();
    if (!line) continue;

    const parts = line.split("|");
    if (parts.length < 10) {
      errors.push(`Línea ${i + 1}: formato inválido (${parts.length} columnas)`);
      continue;
    }

    const description = parts[9].trim();
    const year = Number(parts[2].trim());
    const month = Number(parts[3].trim());
    const rawAmount = parts[4].trim();
    const rawAmountPayed = parts[5].trim();
    const rawStatus = parts[6].trim();
    const rawDueDate = parts[7].trim();
    const rawPaymentDate = parts[8].trim();

    try {
      const amount = parseAmount(rawAmount);
      if (amount === null) {
        errors.push(`Línea ${i + 1} ("${description}"): monto inválido`);
        continue;
      }

      const amountPayed = parseAmount(rawAmountPayed);
      const dueDate = parseDate(rawDueDate);
      const paymentDate = parseDate(rawPaymentDate);

      if (!dueDate) {
        errors.push(`Línea ${i + 1} ("${description}"): fecha de vencimiento inválida`);
        continue;
      }

      const existing = await prisma.expense.findFirst({
        where: { description, year, month },
      });
      if (existing) {
        skipped++;
        continue;
      }

      let periodicExpenseId: number | null = null;
      if (parts[1].trim()) {
        const periodic = await prisma.periodicExpense.findFirst({
          where: { description: { equals: description, mode: "insensitive" } },
        });
        if (periodic) {
          periodicExpenseId = periodic.id;
        }
      }

      const status = rawStatus === "PAYED" ? PaymentStatus.PAYED : PaymentStatus.PENDING;

      await prisma.expense.create({
        data: {
          description,
          year,
          month,
          amount,
          amountPayed,
          status,
          dueDate,
          paymentDate,
          periodicExpenseId,
        },
      });

      imported++;
    } catch (err) {
      const message = err instanceof Error ? err.message : String(err);
      errors.push(`Línea ${i + 1} ("${description}"): ${message}`);
      logger.error({ err, description }, "Error importing expense");
    }
  }

  return c.json({
    imported,
    skipped,
    errors: errors.length > 0 ? errors : undefined,
  });
}
