import { prisma } from "@/lib/prisma";
import { requireUser, requirePermission, withGuard } from "@/lib/guard";
import { parseBody, ok } from "@/lib/http";
import { kpiSchema } from "@/lib/validators";
import type { Prisma } from "@prisma/client";
import { spanAllDepartmentIds, departmentIdFilter } from "@/lib/dept-scope";

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

const KPI_INCLUDE = {
  company: { select: { id: true, name: true } },
  department: { select: { id: true, name: true } },
  assignedUser: { select: { id: true, name: true, position: true } },
  channels: { select: { id: true, name: true } },
} satisfies Prisma.KpiIndicatorInclude;

// GET /api/kpis — list indicators. Optional ?type=DEPARTMENT|PERSONAL and
// ?position=... filters. Pass ?year=&month= to include that month's value for
// each KPI (monthly tracking); omit them to get all monthly values.
export const GET = withGuard(async (req: Request) => {
  await requireUser();
  const url = new URL(req.url);
  const type = url.searchParams.get("type");
  const position = url.searchParams.get("position");
  const companyId = url.searchParams.get("companyId");
  const year = Number(url.searchParams.get("year"));
  const month = Number(url.searchParams.get("month"));
  const hasMonth = Number.isInteger(year) && month >= 1 && month <= 12;

  const departmentId = url.searchParams.get("departmentId");
  const spanIds = await spanAllDepartmentIds();

  const where: Prisma.KpiIndicatorWhereInput = {};
  if (type === "DEPARTMENT" || type === "PERSONAL") where.type = type;
  if (position) where.assignedPosition = position;
  if (departmentId) where.departmentId = departmentIdFilter(departmentId, spanIds);
  // A specific company also surfaces cross-cutting (HQ) KPIs, which serve all
  // companies regardless of their own company tag.
  if (companyId) {
    where.AND = [
      {
        OR: [
          { companyId },
          ...(spanIds.length ? [{ departmentId: { in: spanIds } }] : []),
        ],
      },
    ];
  }

  const kpis = await prisma.kpiIndicator.findMany({
    where,
    include: {
      ...KPI_INCLUDE,
      monthlyValues: hasMonth ? { where: { year, month } } : true,
    },
    orderBy: [{ type: "asc" }, { name: "asc" }],
  });
  return ok(kpis);
});

// POST /api/kpis — create an indicator (Manager-tier and above).
export const POST = withGuard(async (req: Request) => {
  await requirePermission("kpis:write");
  const data = await parseBody(req, kpiSchema);
  const isPersonal = data.type === "PERSONAL";
  const kpi = await prisma.kpiIndicator.create({
    data: {
      name: data.name,
      description: data.description ?? null,
      targetValue: data.targetValue,
      currentValue: data.currentValue ?? 0,
      unit: data.unit,
      period: data.period,
      type: data.type,
      category: data.category ?? "OTHER",
      // DEPARTMENT KPIs roll up to a company; PERSONAL KPIs target one person.
      companyId: isPersonal ? null : data.companyId ?? null,
      // The owning functional department (applies to either KPI type).
      departmentId: data.departmentId ?? null,
      assignedUserId: isPersonal ? data.assignedUserId ?? null : null,
      assignedPosition: isPersonal ? data.assignedPosition ?? null : null,
      weightage: data.weightage ?? 0,
      ...(data.channelIds && {
        channels: { connect: data.channelIds.map((id) => ({ id })) },
      }),
    },
    include: KPI_INCLUDE,
  });
  return ok(kpi, 201);
});
