import 'dotenv/config';
import { PrismaClient } from '@prisma/client';

type CliOptions = {
  empresaId?: string;
  cuentaId?: string;
  modo: 'AUTOMATICO' | 'CONFIRMACION' | 'MANUAL';
};

const prisma = new PrismaClient();

function parseArgs(argv: string[]): CliOptions {
  const options: CliOptions = {
    modo: 'AUTOMATICO',
  };

  for (const raw of argv) {
    if (!raw.startsWith('--')) continue;
    const [key, value = ''] = raw.slice(2).split('=');
    if (key === 'empresa' && value) options.empresaId = value.trim();
    if (key === 'cuenta' && value) options.cuentaId = value.trim();
    if (key === 'modo' && value) {
      const normalized = value.trim().toUpperCase();
      if (normalized === 'AUTOMATICO' || normalized === 'CONFIRMACION' || normalized === 'MANUAL') {
        options.modo = normalized;
      }
    }
  }

  return options;
}

async function resolveEmpresaId(options: CliOptions): Promise<string> {
  if (options.empresaId) return options.empresaId;
  if (process.env.HOLDING_EMPRESA_ID) return process.env.HOLDING_EMPRESA_ID;

  const empresa = await prisma.empresas.findFirst({
    where: { active: true },
    select: { id: true },
    orderBy: { created_at: 'asc' },
  });

  if (!empresa) {
    throw new Error('No se encontró una empresa activa para configurar Tesorería');
  }
  return empresa.id;
}

async function resolveCuentaId(empresaId: string, options: CliOptions): Promise<string> {
  if (options.cuentaId) {
    const cuenta = await prisma.tes_cuentas.findFirst({
      where: {
        id: options.cuentaId,
        empresa_id: empresaId,
        activo: true,
      },
      select: { id: true },
    });
    if (!cuenta) {
      throw new Error(`La cuenta ${options.cuentaId} no existe o no está activa para la empresa ${empresaId}`);
    }
    return cuenta.id;
  }

  const existente = await prisma.tes_cuentas.findFirst({
    where: {
      empresa_id: empresaId,
      activo: true,
    },
    orderBy: [{ tipo: 'asc' }, { created_at: 'asc' }],
    select: { id: true, nombre: true },
  });
  if (existente) {
    console.log(`Usando cuenta de Tesorería existente: ${existente.nombre} (${existente.id})`);
    return existente.id;
  }

  const creada = await prisma.tes_cuentas.create({
    data: {
      empresa_id: empresaId,
      nombre: 'Tesorería Pagos Proveedor',
      tipo: 'CAJA_CHICA',
      moneda: 'PYG',
      saldo_inicial: 0,
      saldo_actual: 0,
      activo: true,
    },
    select: { id: true, nombre: true },
  });
  console.log(`Cuenta de Tesorería creada: ${creada.nombre} (${creada.id})`);
  return creada.id;
}

async function main() {
  const options = parseArgs(process.argv.slice(2));
  const empresaId = await resolveEmpresaId(options);

  const empresa = await prisma.empresas.findUnique({
    where: { id: empresaId },
    select: { id: true, active: true },
  });
  if (!empresa) {
    throw new Error(`La empresa ${empresaId} no existe`);
  }
  if (!empresa.active) {
    throw new Error(`La empresa ${empresaId} está inactiva`);
  }

  const cuentaId = await resolveCuentaId(empresaId, options);

  const reglaExistente = await prisma.tes_reglas.findFirst({
    where: { empresa_id: empresaId, tipo_operacion: 'PAGO_PROVEEDOR', medio_pago_id: null },
    select: { id: true },
  });
  const selectRegla = {
    id: true,
    empresa_id: true,
    tipo_operacion: true,
    cuenta_id: true,
    modo: true,
    activo: true,
  };
  const regla = reglaExistente
    ? await prisma.tes_reglas.update({
        where: { id: reglaExistente.id },
        data: { cuenta_id: cuentaId, modo: options.modo, activo: true, updated_at: new Date() },
        select: selectRegla,
      })
    : await prisma.tes_reglas.create({
        data: { empresa_id: empresaId, tipo_operacion: 'PAGO_PROVEEDOR', cuenta_id: cuentaId, modo: options.modo, activo: true },
        select: selectRegla,
      });

  console.log('Regla de Tesorería lista para flujo OP->Tesorería:');
  console.log(JSON.stringify(regla, null, 2));
}

main()
  .catch((error) => {
    console.error('[setup-tesoreria-pago-proveedor] Error:', error.message || error);
    process.exitCode = 1;
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
