import type { Request, Response, NextFunction } from 'express';
import * as impuestosService from '../services/impuestos.service.js';
import { prisma } from '../config/database.js';
import { AppError } from '../middlewares/error.middleware.js';

function parseConciliacion(req: Request): boolean {
  return req.query.conciliacion === 'true' || req.query.conciliacion === '1';
}

function parseFlag(req: Request, key: string, defaultValue = true): boolean {
  const v = req.query[key];
  if (v === undefined || v === null) return defaultValue;
  return v === 'true' || v === '1';
}

function effectiveTenantId(req: Request): string {
  return req.viewingTenantId || req.user!.tenantId;
}

export async function getIvaMensual(req: Request, res: Response, next: NextFunction) {
  try {
    if (!req.tenantPool) {
      return next(new AppError(400, 'Tenant no configurado'));
    }

    const año = parseInt(req.query.año as string) || new Date().getFullYear();
    const conciliacion = parseConciliacion(req);
    const contribuyenteId = (req.query.contribuyenteId as string) || null;
    const considerarActivos = parseFlag(req, 'considerarActivos', true);
    const considerarNCs = parseFlag(req, 'considerarNCs', true);
    const data = await impuestosService.getIvaMensual(req.tenantPool, año, effectiveTenantId(req), conciliacion, contribuyenteId, considerarActivos, considerarNCs);
    res.json(data);
  } catch (error) {
    next(error);
  }
}

export async function getIsrMensual(req: Request, res: Response, next: NextFunction) {
  try {
    if (!req.tenantPool) {
      return next(new AppError(400, 'Tenant no configurado'));
    }
    const año = parseInt(req.query.año as string) || new Date().getFullYear();
    const conciliacion = parseConciliacion(req);
    const contribuyenteId = (req.query.contribuyenteId as string) || null;
    const regimenClave = (req.query.regimenClave as string) || null;
    const considerarActivos = parseFlag(req, 'considerarActivos', true);
    const considerarNCs = parseFlag(req, 'considerarNCs', true);
    const data = await impuestosService.getIsrMensual(req.tenantPool, año, effectiveTenantId(req), conciliacion, contribuyenteId, regimenClave, considerarActivos, considerarNCs);
    res.json(data);
  } catch (error) {
    next(error);
  }
}

export async function getResumenIva(req: Request, res: Response, next: NextFunction) {
  try {
    if (!req.tenantPool) {
      return next(new AppError(400, 'Tenant no configurado'));
    }

    const now = new Date();
    const y = now.getFullYear();
    const m = now.getMonth() + 1;
    const lastDay = new Date(y, m, 0).getDate();
    const fechaInicio = (req.query.fechaInicio as string) || `${y}-${String(m).padStart(2, '0')}-01`;
    const fechaFin = (req.query.fechaFin as string) || `${y}-${String(m).padStart(2, '0')}-${String(lastDay).padStart(2, '0')}`;
    const conciliacion = parseConciliacion(req);
    const contribuyenteId = (req.query.contribuyenteId as string) || null;
    const considerarActivos = parseFlag(req, 'considerarActivos', true);
    const considerarNCs = parseFlag(req, 'considerarNCs', true);

    const resumen = await impuestosService.getResumenIva(req.tenantPool, fechaInicio, fechaFin, effectiveTenantId(req), conciliacion, contribuyenteId, considerarActivos, considerarNCs);
    res.json(resumen);
  } catch (error) {
    next(error);
  }
}

export async function getResumenIsr(req: Request, res: Response, next: NextFunction) {
  try {
    if (!req.tenantPool) {
      return next(new AppError(400, 'Tenant no configurado'));
    }

    const now = new Date();
    const y = now.getFullYear();
    const m = now.getMonth() + 1;
    const lastDay = new Date(y, m, 0).getDate();
    const fechaInicio = (req.query.fechaInicio as string) || `${y}-${String(m).padStart(2, '0')}-01`;
    const fechaFin = (req.query.fechaFin as string) || `${y}-${String(m).padStart(2, '0')}-${String(lastDay).padStart(2, '0')}`;
    const conciliacion = parseConciliacion(req);
    const contribuyenteId = (req.query.contribuyenteId as string) || null;
    const considerarActivos = parseFlag(req, 'considerarActivos', true);
    const considerarNCs = parseFlag(req, 'considerarNCs', true);

    const resumen = await impuestosService.getResumenIsr(req.tenantPool, fechaInicio, fechaFin, effectiveTenantId(req), conciliacion, contribuyenteId, considerarActivos, considerarNCs);
    res.json(resumen);
  } catch (error) {
    next(error);
  }
}

export async function getResumenIsrDesglosado(req: Request, res: Response, next: NextFunction) {
  try {
    if (!req.tenantPool) {
      return next(new AppError(400, 'Tenant no configurado'));
    }

    // fechaFin define mes_final + año. Default: último día del mes corriente.
    const now = new Date();
    const y = now.getFullYear();
    const m = now.getMonth() + 1;
    const lastDay = new Date(y, m, 0).getDate();
    const fechaFin = (req.query.fechaFin as string) || `${y}-${String(m).padStart(2, '0')}-${String(lastDay).padStart(2, '0')}`;
    const conciliacion = parseConciliacion(req);
    const contribuyenteId = (req.query.contribuyenteId as string) || null;
    const considerarActivos = parseFlag(req, 'considerarActivos', true);
    const considerarNCs = parseFlag(req, 'considerarNCs', true);

    const desglose = await impuestosService.getResumenIsrDesglosado(
      req.tenantPool,
      fechaFin,
      effectiveTenantId(req),
      conciliacion,
      contribuyenteId,
      considerarActivos,
      considerarNCs,
    );
    res.json(desglose);
  } catch (error) {
    next(error);
  }
}

export async function getCoeficiente(req: Request, res: Response, next: NextFunction) {
  try {
    const anio = parseInt(req.query.anio as string) || new Date().getFullYear();
    const tenantId = effectiveTenantId(req);
    const row = await prisma.coeficienteUtilidad.findUnique({
      where: { tenantId_anio: { tenantId, anio } },
    });
    res.json({ anio, coeficiente: row ? Number(row.coeficiente) : null });
  } catch (error) {
    next(error);
  }
}

export async function setCoeficiente(req: Request, res: Response, next: NextFunction) {
  try {
    if (req.user!.role !== 'owner') {
      return res.status(403).json({ message: 'Solo el dueño puede configurar el coeficiente' });
    }

    const { anio, coeficiente } = req.body;
    if (!anio || coeficiente === undefined || coeficiente === null) {
      return res.status(400).json({ message: 'anio y coeficiente son requeridos' });
    }

    const tenantId = effectiveTenantId(req);
    const row = await prisma.coeficienteUtilidad.upsert({
      where: { tenantId_anio: { tenantId, anio } },
      update: { coeficiente },
      create: { tenantId, anio, coeficiente },
    });

    res.json({ anio: row.anio, coeficiente: Number(row.coeficiente) });
  } catch (error) {
    next(error);
  }
}
