﻿import { NextResponse } from "next/server";

import {
  requireAnyPermission,
  employeeScopeFromAccess,
  requirePermission,
} from "@/lib/authorization";
import {
  deleteEmployeFeed,
  getEmployeDetails,
  updateEmployeFeed,
} from "../../../../server/employes.server";
import { employeUpdateSchema } from "../../../../validators/employes";
import { DependentRecordsError } from "../../../../lib/errors";

type PrismaErrorWithCode = {
  code?: string;
};

function hasPrismaCode(
  error: unknown,
  code: string,
): error is PrismaErrorWithCode {
  return (
    typeof error === "object" &&
    error !== null &&
    "code" in error &&
    (error as PrismaErrorWithCode).code === code
  );
}

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

function parseCos(cosParam: string) {
  const cos = Number(cosParam);

  if (!Number.isInteger(cos)) {
    return null;
  }

  return cos;
}

export async function GET(_request: Request, { params }: RouteContext) {
  const auth = await requireAnyPermission(
    _request,
    [
      "alertes",
      "etat_civil",
      "contrats",
      "absences",
      "visites_medicales",
      "sanctions",
      "fiches_paie",
      "autres",
    ],
    "read",
  );

  if (!auth.ok) return auth.response;

  const { cos: cosParam } = await params;
  const cos = parseCos(cosParam);

  if (cos === null) {
    return NextResponse.json(
      { message: "Invalid COS parameter" },
      { status: 400 },
    );
  }

  const data = await getEmployeDetails(
    cos,
    employeeScopeFromAccess(auth.access),
  );

  if (!data.employe) {
    return NextResponse.json({ message: "Employe not found" }, { status: 404 });
  }

  const canReadCivilState = auth.access.permissions.etat_civil.canRead;
  const publicEmployee = canReadCivilState
    ? data.employe
    : {
        COS: data.employe.COS,
        TIT: data.employe.TIT,
        NSA: data.employe.NSA,
        PRE: data.employe.PRE,
        Actif: data.employe.Actif,
      };

  return NextResponse.json({
    message: "Employe retrieved successfully",
    employe: publicEmployee,
  });
}

export async function PUT(request: Request, { params }: RouteContext) {
  const auth = await requirePermission(request, "etat_civil", "write");

  if (!auth.ok) return auth.response;

  const { cos: cosParam } = await params;
  const cos = parseCos(cosParam);

  if (cos === null) {
    return NextResponse.json(
      { message: "Invalid COS parameter" },
      { status: 400 },
    );
  }

  const visibleEmployee = await getEmployeDetails(
    cos,
    employeeScopeFromAccess(auth.access),
  );

  if (!visibleEmployee.employe) {
    return NextResponse.json({ message: "Employe not found" }, { status: 404 });
  }

  let body: unknown;

  try {
    body = await request.json();
  } catch {
    return NextResponse.json({ message: "Invalid JSON body" }, { status: 400 });
  }

  const parsed = employeUpdateSchema.safeParse(body);

  if (!parsed.success) {
    return NextResponse.json(
      { message: "Invalid body parameters", issues: parsed.error.issues },
      { status: 400 },
    );
  }

  const data = await updateEmployeFeed(cos, parsed.data);

  if (!data.employe) {
    return NextResponse.json({ message: "Employe not found" }, { status: 404 });
  }

  return NextResponse.json({
    message: "Employe updated successfully",
    ...data,
  });
}

export async function DELETE(_request: Request, { params }: RouteContext) {
  const auth = await requirePermission(_request, "etat_civil", "write");

  if (!auth.ok) return auth.response;

  const { cos: cosParam } = await params;
  const cos = parseCos(cosParam);

  if (cos === null) {
    return NextResponse.json(
      { message: "Invalid COS parameter" },
      { status: 400 },
    );
  }

  const visibleEmployee = await getEmployeDetails(
    cos,
    employeeScopeFromAccess(auth.access),
  );

  if (!visibleEmployee.employe) {
    return NextResponse.json({ message: "Employe not found" }, { status: 404 });
  }

  try {
    const data = await deleteEmployeFeed(cos);

    if (!data.employe) {
      return NextResponse.json(
        { message: "Employe not found" },
        { status: 404 },
      );
    }

    return NextResponse.json({
      message: "Employe deleted successfully",
      ...data,
    });
  } catch (err: unknown) {
    if (err instanceof DependentRecordsError) {
      return NextResponse.json(
        { message: "Impossible to delete employee: dependent records exist" },
        { status: 409 },
      );
    }

    // Prisma foreign key constraint (or other) may still surface as an object with a code
    if (hasPrismaCode(err, "P2003")) {
      return NextResponse.json(
        { message: "Impossible to delete employee: dependent records exist" },
        { status: 409 },
      );
    }

    return NextResponse.json(
      { message: "Internal Server Error" },
      { status: 500 },
    );
  }
}
