import { Router, Response } from 'express';
import { authenticate } from '../middleware/auth';
import { requireRole } from '../middleware/requireRole';
import { validate } from '../middleware/validate';
import { DateRangeQuerySchema } from '@nobel/shared';
import prisma from '../lib/prisma';

const router = Router();
router.use(authenticate, requireRole('admin', 'accounts'), validate(DateRangeQuerySchema, 'query'));

router.get('/revenue', async (req, res: Response) => {
  const { from, to } = req.query as Record<string, string>;
  const fromDate = from ? new Date(from) : new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
  const toDate = to ? new Date(to) : new Date();

  const receipts = await prisma.receipt.findMany({
    where: { date: { gte: fromDate, lte: toDate }, status: 'paid' },
    include: { order: { include: { items: true } } },
    orderBy: { date: 'asc' },
  });

  let revenue = 0;
  const byDay: Record<string, number> = {};

  for (const r of receipts) {
    // Prefer the immutable snapshot taken at finalize; fall back to
    // recomputing from line items for receipts created before snapshots.
    let amount = r.total;
    if (amount <= 0) {
      const items = r.order.items;
      const subtotal = items.reduce((s, i) => s + i.qty * i.unitPrice, 0);
      const taxable = Math.max(0, subtotal - r.order.discount);
      const tax = taxable * r.order.taxRate;
      amount = taxable + tax;
    }
    revenue += amount;
    const day = r.date.toISOString().slice(0, 10);
    byDay[day] = (byDay[day] || 0) + amount;
  }

  res.json({
    total: Math.round(revenue * 100) / 100,
    count: receipts.length,
    byDay: Object.entries(byDay).map(([date, amount]) => ({ date, amount: Math.round(amount * 100) / 100 })),
  });
});

router.get('/orders', async (req, res: Response) => {
  const { from, to } = req.query as Record<string, string>;
  const fromDate = from ? new Date(from) : new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
  const toDate = to ? new Date(to) : new Date();

  const orders = await prisma.workOrder.findMany({
    where: { createdAt: { gte: fromDate, lte: toDate } },
    select: { status: true },
  });

  const breakdown: Record<string, number> = {};
  for (const o of orders) {
    breakdown[o.status] = (breakdown[o.status] || 0) + 1;
  }

  res.json({ total: orders.length, breakdown });
});

router.get('/customers', async (_req, res: Response) => {
  const customers = await prisma.customer.findMany({
    where: { deletedAt: null },
    include: {
      orders: {
        where: { status: 'paid' },
        include: { items: true },
      },
    },
    orderBy: { createdAt: 'desc' },
  });

  const withLtv = customers.map((c) => {
    const ltv = c.orders.reduce((sum, o) => {
      const subtotal = o.items.reduce((s, i) => s + i.qty * i.unitPrice, 0);
      const taxable = Math.max(0, subtotal - o.discount);
      return sum + taxable + taxable * o.taxRate;
    }, 0);
    return {
      id: c.id,
      name: c.name,
      tier: c.tier,
      orderCount: c.orders.length,
      ltv: Math.round(ltv * 100) / 100,
    };
  });

  withLtv.sort((a, b) => b.ltv - a.ltv);

  res.json({ data: withLtv.slice(0, 20) });
});

router.get('/inventory', async (_req, res: Response) => {
  const items = await prisma.inventoryItem.findMany({ where: { deletedAt: null } });
  const lowStock = items.filter((i) => i.stock > 0 && i.stock <= i.reorderLevel);
  const outOfStock = items.filter((i) => i.stock <= 0);
  const totalValue = items.reduce((s, i) => s + i.stock * i.cost, 0);

  res.json({
    total: items.length,
    lowStock: lowStock.length,
    outOfStock: outOfStock.length,
    totalValue: Math.round(totalValue * 100) / 100,
    lowStockItems: lowStock,
    outOfStockItems: outOfStock,
  });
});

export default router;
