import { prisma } from "@/lib/prisma";
import { requirePermission, withGuard } from "@/lib/guard";
import { ok } from "@/lib/http";
import { progressPct } from "@/lib/utils";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";

// GET /api/reports/monthly?year=&month= — a monthly KPI summary for the whole
// team, grouped into department (by company) and personal (by staff). Used by
// the printable monthly report (Manager-tier).
export const GET = withGuard(async (req: Request) => {
  await requirePermission("dashboard:viewTeam");
  const url = new URL(req.url);
  const now = new Date();
  const year = Number(url.searchParams.get("year")) || now.getFullYear();
  const month = Number(url.searchParams.get("month")) || now.getMonth() + 1;
  const prev = month === 1 ? { y: year - 1, m: 12 } : { y: year, m: month - 1 };

  const kpis = await prisma.kpiIndicator.findMany({
    include: {
      company: { select: { id: true, name: true } },
      assignedUser: { select: { id: true, name: true, position: true } },
      channels: { select: { id: true, name: true } },
      monthlyValues: {
        where: { OR: [{ year, month }, { year: prev.y, month: prev.m }] },
      },
    },
    orderBy: { name: "asc" },
  });

  // Resolve each KPI to this month's target/actual, plus last month for trend.
  const resolved = kpis.map((k) => {
    const mv = k.monthlyValues.find((m) => m.year === year && m.month === month);
    const pv = k.monthlyValues.find((m) => m.year === prev.y && m.month === prev.m);
    const target = mv?.targetValue ?? k.targetValue;
    const actual = mv?.actualValue ?? 0;
    const prevActual = pv?.actualValue ?? null;
    return {
      id: k.id,
      name: k.name,
      unit: k.unit,
      type: k.type,
      category: k.category,
      weightage: k.weightage,
      company: k.company,
      assignedUser: k.assignedUser,
      channels: k.channels.map((c) => c.name),
      target,
      actual,
      prevActual,
      delta: prevActual === null ? null : Math.round((actual - prevActual) * 100) / 100,
      note: mv?.note ?? null,
      pct: progressPct(actual, target),
    };
  });

  const weightedScore = (items: { pct: number; weightage: number }[]) => {
    if (items.length === 0) return 0;
    const tw = items.reduce((s, k) => s + k.weightage, 0);
    return tw
      ? Math.round(items.reduce((s, k) => s + k.pct * k.weightage, 0) / tw)
      : Math.round(items.reduce((s, k) => s + k.pct, 0) / items.length);
  };
  const avgScore = (items: { pct: number }[]) =>
    items.length ? Math.round(items.reduce((s, k) => s + k.pct, 0) / items.length) : 0;

  // ── Department KPIs grouped by company ──
  const deptKpis = resolved.filter((k) => k.type === "DEPARTMENT");
  const companyMap = new Map<string, { companyId: string | null; companyName: string; kpis: typeof deptKpis }>();
  for (const k of deptKpis) {
    const key = k.company?.id ?? "_none";
    if (!companyMap.has(key)) {
      companyMap.set(key, {
        companyId: k.company?.id ?? null,
        companyName: k.company?.name ?? "Unassigned",
        kpis: [],
      });
    }
    companyMap.get(key)!.kpis.push(k);
  }
  const department = [...companyMap.values()].map((g) => ({
    ...g,
    score: weightedScore(g.kpis),
  }));

  // ── Personal KPIs grouped by staff member ──
  const personalKpis = resolved.filter((k) => k.type === "PERSONAL");
  const staffMap = new Map<string, { userId: string | null; name: string; position: string | null; kpis: typeof personalKpis }>();
  for (const k of personalKpis) {
    const key = k.assignedUser?.id ?? "_none";
    if (!staffMap.has(key)) {
      staffMap.set(key, {
        userId: k.assignedUser?.id ?? null,
        name: k.assignedUser?.name ?? "Unassigned",
        position: k.assignedUser?.position ?? null,
        kpis: [],
      });
    }
    staffMap.get(key)!.kpis.push(k);
  }
  const personal = [...staffMap.values()].map((g) => ({
    ...g,
    score: avgScore(g.kpis),
  }));

  return ok({
    year,
    month,
    departmentScore: weightedScore(deptKpis),
    personalScore: avgScore(personalKpis),
    totals: {
      departmentKpis: deptKpis.length,
      personalKpis: personalKpis.length,
      staff: personal.filter((p) => p.userId).length,
    },
    department,
    personal,
  });
});
