import { prisma } from '@/lib/prisma';
import { InvoiceStatus, MovementType } from '@prisma/client';

export async function getSalesReport(from?: string, to?: string) {
  const startDate = from ? new Date(from) : new Date(new Date().setHours(0, 0, 0, 0));
  const endDate = to ? new Date(to) : new Date(new Date().setHours(23, 59, 59, 999));

  // 1. Facturas pagadas en el rango de fechas
  const invoices = await prisma.invoice.findMany({
    where: {
      status: InvoiceStatus.PAID,
      createdAt: {
        gte: startDate,
        lte: endDate,
      },
    },
    include: {
      payments: true,
      order: {
        include: {
          items: {
            include: { product: { select: { name: true, category: { select: { name: true } } } } },
          },
        },
      },
    },
    orderBy: { createdAt: 'desc' },
  });

  // 2. Cálculo de Totales
  let totalSales = 0;
  let totalTax = 0;
  let totalTips = 0;
  let totalDiscounts = 0;
  const paymentMethodsBreakdown: Record<string, number> = {
    CASH: 0,
    CREDIT_CARD: 0,
    DEBIT_CARD: 0,
    QR_TRANSFER: 0,
  };

  const productSalesMap: Record<string, { name: string; category: string; quantity: number; revenue: number }> = {};

  invoices.forEach((inv) => {
    totalSales += Number(inv.total);
    totalTax += Number(inv.taxAmount);
    totalTips += Number(inv.tipAmount);
    totalDiscounts += Number(inv.discountAmount);

    inv.payments.forEach((p) => {
      paymentMethodsBreakdown[p.method] = (paymentMethodsBreakdown[p.method] || 0) + Number(p.amount);
    });

    inv.order?.items.forEach((item) => {
      if (!productSalesMap[item.productId]) {
        productSalesMap[item.productId] = {
          name: item.product.name,
          category: item.product.category?.name || 'General',
          quantity: 0,
          revenue: 0,
        };
      }
      productSalesMap[item.productId].quantity += item.quantity;
      productSalesMap[item.productId].revenue += Number(item.subtotal);
    });
  });

  const topProducts = Object.values(productSalesMap).sort((a, b) => b.quantity - a.quantity).slice(0, 10);

  return {
    period: {
      from: startDate.toISOString(),
      to: endDate.toISOString(),
    },
    summary: {
      totalInvoices: invoices.length,
      totalSales,
      totalTax,
      totalTips,
      totalDiscounts,
      netSales: totalSales - totalTax - totalTips,
    },
    paymentMethodsBreakdown,
    topProducts,
    recentInvoices: invoices.map((i) => ({
      id: i.id,
      invoiceNumber: i.invoiceNumber,
      total: Number(i.total),
      taxAmount: Number(i.taxAmount),
      createdAt: i.createdAt,
      orderNumber: i.order?.orderNumber,
    })),
  };
}

export async function getInventoryReport() {
  const inventoryItems = await prisma.inventory.findMany({
    include: {
      product: {
        select: {
          id: true,
          name: true,
          price: true,
          cost: true,
          unitMeasure: true,
          category: { select: { name: true } },
        },
      },
      warehouse: { select: { id: true, name: true } },
    },
    orderBy: { product: { name: 'asc' } },
  });

  let totalCostValuation = 0;
  let totalRetailValuation = 0;
  let lowStockCount = 0;
  const warehouseBreakdown: Record<string, { warehouseName: string; totalItems: number; costValuation: number }> = {};

  inventoryItems.forEach((inv) => {
    const qty = Number(inv.quantity);
    const min = Number(inv.minStock);
    const cost = Number(inv.product.cost);
    const price = Number(inv.product.price);

    const costVal = qty * cost;
    const retailVal = qty * price;

    totalCostValuation += costVal;
    totalRetailValuation += retailVal;

    if (qty <= min) {
      lowStockCount++;
    }

    if (!warehouseBreakdown[inv.warehouseId]) {
      warehouseBreakdown[inv.warehouseId] = {
        warehouseName: inv.warehouse.name,
        totalItems: 0,
        costValuation: 0,
      };
    }
    warehouseBreakdown[inv.warehouseId].totalItems += qty;
    warehouseBreakdown[inv.warehouseId].costValuation += costVal;
  });

  // Ultimos 20 movimientos de kardex
  const recentMovements: any[] = await prisma.stockMovement.findMany({
    take: 20,
    orderBy: { createdAt: 'desc' },
    include: {
      product: { select: { name: true } },
      warehouse: { select: { name: true } },
    },
  });

  return {
    summary: {
      totalProducts: inventoryItems.length,
      lowStockCount,
      totalCostValuation,
      totalRetailValuation,
      potentialProfit: totalRetailValuation - totalCostValuation,
    },
    warehouseBreakdown: Object.values(warehouseBreakdown),
    recentMovements: recentMovements.map((m) => ({
      id: m.id,
      productName: m.product.name,
      warehouseName: m.warehouse.name,
      quantity: Number(m.quantity),
      type: m.type,
      reason: m.reason,
      userName: 'Sistema',
      createdAt: m.createdAt,
    })),
    inventoryList: inventoryItems.map((inv) => ({
      id: inv.id,
      productName: inv.product.name,
      categoryName: inv.product.category?.name || 'General',
      warehouseName: inv.warehouse.name,
      quantity: Number(inv.quantity),
      minStock: Number(inv.minStock),
      cost: Number(inv.product.cost),
      price: Number(inv.product.price),
      isLowStock: Number(inv.quantity) <= Number(inv.minStock),
    })),
  };
}
