import { NextResponse } from "next/server";

import {
  employeeScopeFromAccess,
  requirePermission,
} from "@/lib/authorization";
import {
  createNightTeamDocuments,
  getEmployeesWithoutMedicalVisit,
  getEntryExitRegister,
  getForeignEmployeesTenderDocument,
  getMonthlyIndicators,
  getNightTeamEmployeeOptions,
  getPayrollElements,
  type NightTeamRequest,
} from "@/services/etats.service";

export const runtime = "nodejs";

type RouteContext = { params: Promise<{ etat: string }> };

function errorResponse(error: unknown) {
  const message = error instanceof Error ? error.message : "REPORT_GENERATION_FAILED";
  const status = ["INVALID_DATE", "INVALID_RANGE", "EMPLOYEES_REQUIRED"].includes(message)
    ? 422
    : message === "EMPLOYEE_NOT_FOUND"
      ? 404
      : 500;

  if (status === 500) console.error("Erreur de génération d'état", error);
  return NextResponse.json(
    { message: status === 500 ? "REPORT_GENERATION_FAILED" : message },
    { status },
  );
}

export async function GET(request: Request, context: RouteContext) {
  const auth = await requirePermission(request, "impressions", "read");
  if (!auth.ok) return auth.response;

  const { etat } = await context.params;
  const url = new URL(request.url);
  const date = url.searchParams.get("date") ?? "";
  const scope = employeeScopeFromAccess(auth.access);

  try {
    let report: unknown;
    if (etat === "indicateurs-mensuels") {
      report = await getMonthlyIndicators(date, scope);
    } else if (etat === "elements-paie") {
      report = await getPayrollElements(date, scope);
    } else if (etat === "salaries-sans-vm") {
      report = await getEmployeesWithoutMedicalVisit(date, scope);
    } else if (etat === "registre-entrees-sorties") {
      report = await getEntryExitRegister(
        url.searchParams.get("from") ?? "",
        url.searchParams.get("to") ?? "",
        scope,
      );
    } else if (etat === "appels-offres-etrangers") {
      report = await getForeignEmployeesTenderDocument(date, scope);
    } else if (etat === "avenant-equipe-nuit") {
      report = await getNightTeamEmployeeOptions(date, scope);
    } else {
      return NextResponse.json({ message: "REPORT_NOT_FOUND" }, { status: 404 });
    }

    return NextResponse.json(
      { report },
      { headers: { "Cache-Control": "private, no-store" } },
    );
  } catch (error) {
    return errorResponse(error);
  }
}

export async function POST(request: Request, context: RouteContext) {
  const auth = await requirePermission(request, "impressions", "read");
  if (!auth.ok) return auth.response;

  const { etat } = await context.params;
  if (etat !== "avenant-equipe-nuit") {
    return NextResponse.json({ message: "REPORT_NOT_FOUND" }, { status: 404 });
  }

  let body: NightTeamRequest;
  try {
    body = (await request.json()) as NightTeamRequest;
  } catch {
    return NextResponse.json({ message: "INVALID_JSON" }, { status: 400 });
  }

  const validEmployees =
    Array.isArray(body?.employees) &&
    body.employees.every(
      (item) =>
        item != null &&
        typeof item === "object" &&
        Number.isInteger(item.cos) &&
        ["OUVRIER", "CHEF_EQUIPE"].includes(item.role),
    );
  if (
    !body ||
    typeof body.startDate !== "string" ||
    typeof body.endDate !== "string" ||
    typeof body.returnDate !== "string" ||
    typeof body.signedAt !== "string" ||
    !validEmployees
  ) {
    return NextResponse.json({ message: "INVALID_DOCUMENT_DATA" }, { status: 422 });
  }

  try {
    const report = await createNightTeamDocuments(
      body,
      employeeScopeFromAccess(auth.access),
    );
    return NextResponse.json(
      { report },
      { status: 201, headers: { "Cache-Control": "private, no-store" } },
    );
  } catch (error) {
    return errorResponse(error);
  }
}
