'use strict';

const fs = require('fs');
const path = require('path');
const express = require('express');
const billing = require('../billing/billing.service');
const billingPrint = require('../billing-print/billing-print.service');
const { limiterRefresh } = require('../../middleware/rateLimiter');

const router = express.Router();

function tenantContext() {
  return {
    tenantId: process.env.ARKHON_CLIENT_ID || process.env.SUCURSAL_ID || 'local',
    branchId: process.env.SUCURSAL_ID || process.env.BILLING_PRINT_BRANCH_CODE || 'principal',
    branchName: process.env.SUCURSAL_NOMBRE || process.env.BILLING_PRINT_BRANCH_NAME || 'Sucursal principal',
  };
}

function clean(value, max = 160) {
  return String(value || '').trim().slice(0, max);
}

function publicTicket(ticket) {
  if (!ticket) return null;
  return {
    id: ticket.id,
    folio: ticket.folio,
    external_ticket_id: ticket.external_ticket_id,
    date: ticket.date,
    payment_method: ticket.payment_method,
    subtotal: Number(ticket.subtotal || 0),
    taxes: Number(ticket.taxes || 0),
    total: Number(ticket.total || 0),
    status: ticket.status,
    branch_name: ticket.branch_name,
    branch_code: ticket.branch_code || ticket.external_branch_id,
  };
}

function publicInvoice(invoice) {
  if (!invoice) return null;
  return {
    id: invoice.id,
    uuid: invoice.uuid,
    folio: invoice.folio,
    customer_rfc: invoice.customer_rfc,
    customer_name: invoice.customer_name,
    status: invoice.status,
    total: Number(invoice.total || 0),
    stamped_at: invoice.stamped_at,
  };
}

function logoPathFromConfig() {
  const config = billingPrint.getConfig();
  const logoPath = clean(config.logoPath, 500);
  if (!logoPath) return '';
  const ext = path.extname(logoPath).toLowerCase();
  if (!['.png', '.jpg', '.jpeg', '.webp', '.svg'].includes(ext)) return '';
  return fs.existsSync(logoPath) ? logoPath : '';
}

router.get('/config', (req, res) => {
  const config = billingPrint.getConfig();
  const ctx = tenantContext();
  res.json({
    ok: true,
    config: {
      title: config.branchName || ctx.branchName || 'Portal de Autofactura',
      branchName: config.branchName || ctx.branchName || '',
      branchCode: config.branchCode || ctx.branchId || '',
      logoUrl: logoPathFromConfig() ? '/api/autofactura/logo' : '',
      line1: config.line1 || 'Escanea el codigo QR para autofacturar.',
      line2: config.line2 || '',
      portalUrl: config.portalUrl || '',
    },
  });
});

router.get('/logo', (req, res) => {
  const logoPath = logoPathFromConfig();
  if (!logoPath) return res.status(404).end();
  res.set('Cache-Control', 'public, max-age=300');
  return res.sendFile(logoPath);
});

router.get('/ticket', async (req, res, next) => {
  try {
    const ticket = await billing.findAutofacturaTicket(
      tenantContext(),
      req.query.csucursal,
      req.query.cfacturacion
    );
    if (!ticket) return res.status(404).json({ ok: false, error: 'No encontramos ese folio para la sucursal indicada.' });
    res.json({ ok: true, ticket: publicTicket(ticket) });
  } catch (err) {
    next(err);
  }
});

router.post('/facturar', limiterRefresh, express.json({ limit: '64kb' }), async (req, res, next) => {
  try {
    const ctx = tenantContext();
    const ticket = await billing.findAutofacturaTicket(ctx, req.body?.csucursal, req.body?.cfacturacion);
    if (!ticket) return res.status(404).json({ ok: false, error: 'No encontramos ese folio para la sucursal indicada.' });
    if (ticket.status !== 'pending') return res.status(409).json({ ok: false, error: 'Este folio ya fue facturado o no esta disponible.' });

    const customerFiscalData = {
      rfc: clean(req.body?.rfc, 13).toUpperCase(),
      customer_rfc: clean(req.body?.rfc, 13).toUpperCase(),
      razon_social: clean(req.body?.razon_social, 255),
      customer_name: clean(req.body?.razon_social, 255),
      codigo_postal: clean(req.body?.codigo_postal, 10),
      postal_code: clean(req.body?.codigo_postal, 10),
      fiscal_regime: clean(req.body?.regimen_fiscal, 20),
      usage_cfdi: clean(req.body?.uso_cfdi, 20),
      payment_method: clean(req.body?.forma_pago, 80) || ticket.payment_method,
      email: clean(req.body?.email, 255),
      concepto: `Consumo ticket ${ticket.folio || ticket.external_ticket_id}`,
    };

    if (!customerFiscalData.rfc || !customerFiscalData.customer_name || !customerFiscalData.postal_code || !customerFiscalData.fiscal_regime || !customerFiscalData.usage_cfdi) {
      return res.status(400).json({ ok: false, error: 'Completa RFC, razon social, CP, regimen fiscal y uso CFDI.' });
    }

    const invoice = await billing.stampTicketInvoice(ctx, ticket.id, customerFiscalData);
    res.json({ ok: true, invoice: publicInvoice(invoice), pending_sync: !!invoice?.pending_sync, message: invoice?.message || 'Factura generada correctamente.' });
  } catch (err) {
    next(err);
  }
});

router.post('/reenviar', limiterRefresh, express.json({ limit: '32kb' }), async (req, res, next) => {
  try {
    const email = clean(req.body?.email, 255);
    if (!email) return res.status(400).json({ ok: false, error: 'Email requerido para reenviar la factura.' });
    const ctx = tenantContext();
    const invoice = await billing.findInvoiceForAutofactura(ctx, req.body?.csucursal, req.body?.cfacturacion);
    if (!invoice) return res.status(404).json({ ok: false, error: 'No encontramos una factura emitida para ese folio.' });
    const result = await billing.sendInvoiceEmail(ctx, invoice.id, email);
    res.json({ ok: true, invoice: publicInvoice(invoice), result });
  } catch (err) {
    next(err);
  }
});

module.exports = router;
