'use strict';

const svc         = require('../services/dashboardCacheService');
const socket      = require('../services/socketService');
const { sanitizeDate, sanitizeInt, sanitizeString } = require('../utils/validate');
const { localDateStr, localYear, localMonth } = require('../utils/localDate');
const { getPool, sql } = require('../db');
const { db } = require('../utils/dbName');

function extractParams(query) {
  return {
    turno:      sanitizeInt(query.turno),
    fecha:      sanitizeDate(query.fecha),
    fechaDesde: sanitizeDate(query.fechaDesde),
    fechaHasta: sanitizeDate(query.fechaHasta),
    estacion:   sanitizeString(query.estacion, 50),
  };
}

async function resumen(req, res, next) {
  try {
    const { turno, fecha, fechaDesde, fechaHasta, estacion } = extractParams(req.query);
    const data = await svc.getResumen(turno, fecha, fechaDesde, fechaHasta, estacion);
    res.json({ ok: true, fecha: fecha || fechaHasta || 'hoy', turno: turno || 'todos', estacion: estacion || 'todas', data });
  } catch (err) { next(err); }
}

async function ventasHora(req, res, next) {
  try {
    const { turno, fecha, fechaDesde, fechaHasta, estacion } = extractParams(req.query);
    const data = await svc.getVentasPorHora(turno, fecha, fechaDesde, fechaHasta, estacion);
    res.json({ ok: true, data });
  } catch (err) { next(err); }
}

async function ventasPeriodo(req, res, next) {
  try {
    const { turno, fecha, fechaDesde, fechaHasta, estacion } = extractParams(req.query);
    const data = await svc.getVentasPorDia(turno, fecha, fechaDesde, fechaHasta, estacion);
    res.json({ ok: true, data });
  } catch (err) { next(err); }
}

async function ventasMes(req, res, next) {
  try {
    const { fecha } = extractParams(req.query);
    const data = await svc.getVentasMes(fecha);
    res.json({ ok: true, data });
  } catch (err) { next(err); }
}

async function formasPago(req, res, next) {
  try {
    const { turno, fecha, fechaDesde, fechaHasta, estacion } = extractParams(req.query);
    const data = await svc.getFormasPago(turno, fecha, fechaDesde, fechaHasta, estacion);
    res.json({ ok: true, data });
  } catch (err) { next(err); }
}

async function ventasServicio(req, res, next) {
  try {
    const { turno, fecha, fechaDesde, fechaHasta, estacion } = extractParams(req.query);
    const data = await svc.getVentasPorServicio(turno, fecha, fechaDesde, fechaHasta, estacion);
    res.json({ ok: true, data });
  } catch (err) { next(err); }
}

async function metasVentas(req, res, next) {
  try {
    const { fecha } = extractParams(req.query);
    const pool    = await getPool();
    const request = pool.request();

    if (fecha) {
      const parts = fecha.split('-');
      const anio  = parseInt(parts[0]);
      const mes   = parseInt(parts[1]);
      request.input('mv_fecha', sql.Date, fecha);
      request.input('mv_anio',  sql.Int,  anio);
      request.input('mv_mes',   sql.Int,  mes);
    } else {
      request.input('mv_fecha', sql.Date, localDateStr());
      request.input('mv_anio',  sql.Int,  localYear());
      request.input('mv_mes',   sql.Int,  localMonth());
    }

    // BUG-FIX: venta_hoy debe incluir cuentas recién pagadas en tempcheques
    // que SR aún no ha consolidado en cheques. Se usa UNION + NOT EXISTS
    // para evitar doble conteo cuando SR finalmente mueve el registro.
    const r = await request.query(`
      SELECT
        -- venta_hoy: cheques de hoy + tempcheques recién pagados sin doble conteo
        ROUND(ISNULL((
          SELECT SUM(u.total) FROM (
            SELECT folio, total FROM ${db()}cheques
            WHERE CAST(fecha AS DATE) = @mv_fecha AND cancelado = 0 AND pagado = 1 AND total > 0
            UNION
            SELECT tc.folio, tc.total FROM ${db()}tempcheques tc
            WHERE CAST(tc.fecha AS DATE) = @mv_fecha
              AND tc.cancelado = 0 AND tc.pagado = 1 AND tc.total > 0
              AND NOT EXISTS (
                SELECT 1 FROM ${db()}cheques ch
                WHERE ch.folio = tc.folio
                  AND CAST(ch.fecha AS DATE) = @mv_fecha
                  AND ch.cancelado = 0 AND ch.pagado = 1
              )
          ) u
        ), 0), 2) AS venta_hoy,
        -- venta_mes y venta_anio: solo cheques históricos consolidados
        ROUND(SUM(CASE WHEN MONTH(fecha) = @mv_mes AND YEAR(fecha) = @mv_anio THEN total ELSE 0 END), 2) AS venta_mes_actual,
        ROUND(SUM(CASE WHEN YEAR(fecha) = @mv_anio                            THEN total ELSE 0 END), 2) AS venta_anio_actual
      FROM ${db()}cheques
      WHERE cancelado = 0 AND pagado = 1 AND YEAR(fecha) = @mv_anio
    `);

    res.json({ ok: true, data: r.recordset[0] });
  } catch (err) { next(err); }
}

async function refresh(req, res, next) {
  try {
    const payload = await socket.pollDB(true);
    res.json({ ok: true, mensaje: 'Dashboard actualizado', datos: payload });
  } catch (err) { next(err); }
}

// BUG FIX: referenciaba `dashCache` sin importarlo — ahora usa `svc` correctamente
async function domiciliosActivos(req, res, next) {
  try {
    const data = await svc.getDomiciliosActivos();
    res.json({ ok: true, data });
  } catch (err) { next(err); }
}

module.exports = { resumen, ventasHora, ventasPeriodo, ventasMes, formasPago, ventasServicio, metasVentas, refresh, domiciliosActivos };
