import { prisma } from "@/lib/prisma";
import type { Prisma } from "@/generated/prisma/client";
import type { ContratCreateInput, ContratUpdateInput } from "@/validators/contrats";
import type { EmployeeAccessScope } from "@/lib/authorization";

type ContratPayload = ContratCreateInput & {
  ID_Contrat?: number | null;
  Id_Salarie?: number | null;
};

function readLegacyNumberField(data: ContratPayload, key: "ID_Contrat" | "Id_Salarie") {
  const value = data[key];
  return typeof value === "number" ? value : null;
}

function buildContratData(
  rest: Omit<ContratCreateInput, "id_contrat" | "id_salarie">,
  idContrat: number | null,
  idSalarie: number | null
) {
  return {
    ...rest,
    ...(idContrat == null ? {} : { ID_Contrat: idContrat }),
    ...(idSalarie == null ? {} : { Id_Salarie: idSalarie }),
  };
}

function buildContractScopeWhere(
  scope: EmployeeAccessScope,
): Prisma.contratsWhereInput {
  const AND: Prisma.contratsWhereInput[] = [];

  if (scope.establishments !== undefined) {
    AND.push({ ETB: { in: scope.establishments } });
  }

  if (scope.sectors !== undefined) {
    AND.push({ Secteur: { in: scope.sectors } });
  }

  if (scope.categories !== undefined) {
    AND.push({ CAT: { in: scope.categories } });
  }

  if (scope.contractTypes !== undefined) {
    AND.push({ TCS: { in: scope.contractTypes } });
  }

  return AND.length > 0 ? { AND } : {};
}

export async function listContrats(
  limit: number,
  offset: number,
  scope: EmployeeAccessScope,
) {
  return prisma.contrats.findMany({
    where: buildContractScopeWhere(scope),
    orderBy: [{ id: "asc" }],
    take: limit,
    skip: offset,
    select: {
      id: true,
      ID_Contrat: true,
      Id_Salarie: true,
      TCS: true,
      MotifContrat: true,
      DAE: true,
      FPE: true,
      ETB: true,
      Secteur: true,
      CAT: true,
    },
  });
}

export async function getContratById(id: number) {
  return prisma.contrats.findUnique({
    where: {
      id,
    },
  });
}

export async function getContratByBusinessId(idContrat: number) {
  return prisma.contrats.findFirst({
    where: {
      ID_Contrat: idContrat,
    },
  });
}

export async function hasContratForSalarie(cos: number) {
  const contrat = await prisma.contrats.findFirst({
    where: {
      Id_Salarie: cos,
    },
    select: {
      id: true,
    },
  });

  return contrat !== null;
}

export async function createContrat(data: ContratCreateInput) {
  const payload = data as ContratPayload;
  const { id_contrat, id_salarie, ...rest } = data;

  const dbIdContrat = id_contrat ?? readLegacyNumberField(payload, "ID_Contrat");
  const dbIdSalarie = id_salarie ?? readLegacyNumberField(payload, "Id_Salarie");

  return prisma.contrats.create({
  data: buildContratData(rest, dbIdContrat, dbIdSalarie) as any,
});
}

export async function updateContratById(id: number, data: ContratUpdateInput) {
  const existing = await prisma.contrats.findUnique({
    where: {
      id: id,
    },
  });

  if(!existing){
    return null;
  }

  const payload = data as ContratPayload;
  const { id_contrat, id_salarie, ...rest } = data;
  const dbIdContrat = id_contrat ?? readLegacyNumberField(payload, "ID_Contrat");
  const dbIdSalarie = id_salarie ?? readLegacyNumberField(payload, "Id_Salarie");

  return prisma.contrats.update({
  where: {
    id: id,
  },
  data: buildContratData(rest, dbIdContrat, dbIdSalarie) as any,
});
}

export async function deleteContratById(id: number) {
  const existing = await prisma.contrats.findUnique({
    where: {
      id: id,
    },
  });

  if(!existing){
    return null;
  }

  return prisma.contrats.delete({
    where: {
      id: id,
    },
  });
}

export async function listContratsBySalarie(cos: number) {
  return prisma.contrats.findMany({
    where: {
      Id_Salarie: cos,
    },
    orderBy: [{ DAE: "desc" }]
  });
}
