import { fromZonedTime } from "date-fns-tz";
import { Request, Response } from "express";
import Operation from "../models/operation";
import { getRateS } from "../services/rateService";
import OperationPayment from "../models/operationPayment";
import User from "../models/User";

/**
 * Versión en desarrollo de los indicadores del dashboard (incompleta).
 *
 * Filtra usuarios con `verificationStatus: "Approved"` creados dentro del rango
 * de fechas indicado, pero actualmente no retorna ninguna respuesta al cliente.
 * Pendiente de completar con el cálculo de métricas y el `res.json` final.
 *
 * @export
 * @async
 * @param {Request} req - Query: `startDate` (YYYY-MM-DD), `endDate` (YYYY-MM-DD), `currency?` (default: "VEF")
 * @param {Response} res
 * @returns {unknown}
 */
export const getIndicatorsNew = async (req: Request, res: Response) => {
  const startDateFilter = req.query.startDate as string;
  const endDateFilter = req.query.endDate as string;
  const currency = (req.query.currency as string) || "VEF";

  const fixedTimeZone = "America/Caracas";

  const startOfDayString = `${startDateFilter}T00:00:00`;
  const endOfDayString = `${endDateFilter}T23:59:59.999`;

  const startOfUtcDay = fromZonedTime(startOfDayString, fixedTimeZone);
  const endOfUtcDay = fromZonedTime(endOfDayString, fixedTimeZone);

  const rate = await getRateS();
  const rateUsd = rate!.usd;

  const resultCLientes = await User.aggregate([
    {
      $match: {
        createdAt: {
          $gte: startOfUtcDay,
          $lte: endOfUtcDay,
        },
        verificationStatus: "Approved",
      },
    },
  ]);
};

/**
 * Retorna los indicadores financieros del dashboard para un rango de fechas.
 *
 * Las fechas se interpretan en zona horaria `America/Caracas` y se convierten a UTC
 * para las consultas en MongoDB.
 *
 * Calcula dos grupos de métricas mediante aggregation:
 * - **Operaciones**: cantidad y monto total de operaciones de crédito creadas en el período
 *   (excluye estados `void` y `rejected`). El monto se convierte según `currency`.
 * - **Deudas/Pagos**: cantidad y monto total de cuotas cuya fecha de pago (`paidAt`) o
 *   fecha de vencimiento (`date`) cae dentro del período. El monto se calcula en la
 *   moneda solicitada usando la tasa del día.
 *
 * @export
 * @async
 * @param {Request} req - Query: `startDate` (YYYY-MM-DD), `endDate` (YYYY-MM-DD), `currency?` (`"VEF"` | `"USD"`, default: `"VEF"`)
 * @param {Response} res
 * @returns {unknown}
 */
export const getIndicators = async (req: Request, res: Response) => {
  const startDateFilter = req.query.startDate as string;
  const endDateFilter = req.query.endDate as string;
  const currency = (req.query.currency as string) || "VEF";

  const fixedTimeZone = "America/Caracas";

  const startOfDayString = `${startDateFilter}T00:00:00`;
  const endOfDayString = `${endDateFilter}T23:59:59.999`;

  const startOfUtcDay = fromZonedTime(startOfDayString, fixedTimeZone);
  const endOfUtcDay = fromZonedTime(endOfDayString, fixedTimeZone);

  const rate = await getRateS();
  const rateUsd = rate!.usd;

  const resultOperations = await Operation.aggregate([
    {
      $match: {
        createdAt: {
          $gte: startOfUtcDay,
          $lte: endOfUtcDay,
        },
        status: {
          $nin: ["void", "rejected"],
        },
      },
    },
    {
      $group: {
        _id: null,
        totalCount: {
          $sum: 1,
        },
        totalAmount: {
          $sum: {
            $multiply: ["$amountUsd", currency === "VEF" ? rateUsd : 1],
          },
        },
      },
    },
  ]);

  const resultDebts = await OperationPayment.aggregate([
    {
      $match: {
        status: {
          $nin: ["void", "rejected"],
        },
        $expr: {
          $and: [
            {
              $gte: [{ $ifNull: ["$paidAt", "$date"] }, startOfUtcDay],
            },
            {
              $lte: [{ $ifNull: ["$paidAt", "$date"] }, endOfUtcDay],
            },
          ],
        },
      },
    },
    {
      $group: {
        _id: null,
        totalCount: {
          $sum: 1,
        },
        totalAmount: {
          $sum: {
            $cond: {
              if: {
                $eq: ["$status", "paid"],
              },
              then: {
                $divide: ["$amountVef", currency === "VEF" ? 1 : rateUsd],
              },
              else: {
                $multiply: ["$amountUsd", currency === "USD" ? 1 : rateUsd],
              },
            },
          },
        },
      },
    },
  ]);

  return res.status(200).json({
    success: true,
    message: "Indicators retrieved successfully",
    data: {
      operationCount:
        resultOperations.length === 0 ? 0 : resultOperations[0].totalCount,
      operationAmount:
        resultOperations.length === 0 ? 0 : resultOperations[0].totalAmount,
      debtCount: resultDebts.length === 0 ? 0 : resultDebts[0].totalCount,
      debtAmount: resultDebts.length === 0 ? 0 : resultDebts[0].totalAmount,
    },
  });
};
