import { z } from "zod";

export const PROCEDURE_REQUEST_TYPES = [
  "DEMANDE_NOUVELLES",
  "LETTRE_RECADRAGE",
  "AVERTISSEMENT_DIRECT",
  "CONVOCATION_SANCTION",
  "CONVOCATION_LICENCIEMENT_RUPTURE",
  "AUTRE",
] as const;

export const PROCEDURE_FOLLOWUP_TYPES = [
  "CONVOCATION_SANCTION",
  "CONVOCATION_LICENCIEMENT_RUPTURE",
] as const;

export const PROCEDURE_DECISION_TYPES = [
  "LETTRE_RECADRAGE",
  "AVERTISSEMENT",
  "MISE_A_PIED",
  "MUTATION_DISCIPLINAIRE",
  "RETROGRADATION",
  "LICENCIEMENT_CAUSE_REELLE_SERIEUSE",
  "LICENCIEMENT_RUPTURE_FAUTE_GRAVE",
  "LICENCIEMENT_RUPTURE_FAUTE_LOURDE",
  "LICENCIEMENT_RUPTURE_INAPTITUDE",
  "AUTRE",
] as const;

const nullableText = (max: number) =>
  z
    .union([z.string().trim().max(max), z.null()])
    .optional()
    .transform((value) => value || null);

const nullableDate = z
  .union([z.iso.date(), z.literal(""), z.null()])
  .optional()
  .transform((value) => value || null);

const nullableDateTime = z
  .union([z.iso.datetime({ local: true }), z.literal(""), z.null()])
  .optional()
  .transform((value) => value || null);

const requestFields = {
  managerName: z.string().trim().min(1).max(255),
  requestType: z.enum(PROCEDURE_REQUEST_TYPES),
  otherType: nullableText(255),
  factsDate: z.iso.date(),
  factsTime: z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/),
  observedBy: z.string().trim().min(1).max(255),
  factsLocation: z.string().trim().min(1).max(255),
  factsDescription: z.string().trim().min(10).max(20000),
  witnesses: nullableText(10000),
  writtenStatements: z.boolean().nullable().optional(),
};

function validateOtherType(
  data: { requestType: string; otherType?: string | null },
  context: z.RefinementCtx,
) {
  if (data.requestType === "AUTRE" && !data.otherType?.trim()) {
    context.addIssue({
      code: "custom",
      path: ["otherType"],
      message: "Le type de demande doit être précisé.",
    });
  }
}

export const procedureRequestCreateSchema = z
  .object(requestFields)
  .superRefine(validateOtherType);

export const procedureRequestUpdateSchema = z
  .object(requestFields)
  .superRefine(validateOtherType);

export const procedureFollowupSchema = z
  .object({
    interviewAt: z.iso.datetime({ local: true }),
    interviewerName: z.string().trim().min(1).max(255),
    employeePresent: z.boolean(),
    accompaniedBy: nullableText(255),
    decisionType: z.enum(PROCEDURE_DECISION_TYPES),
    otherDecision: nullableText(255),
    suspensionDays: z.coerce.number().int().min(1).max(9).nullable().optional(),
    suspensionStart: nullableDate,
    suspensionEnd: nullableDate,
    decisionReasons: z.string().trim().min(10).max(20000),
    factsAcknowledged: z.boolean(),
    employeeStatement: nullableText(20000),
    decisionMakerName: z.string().trim().min(1).max(255),
    hrValidationSentAt: nullableDateTime,
    notificationSentAt: nullableDateTime,
  })
  .superRefine((data, context) => {
    if (data.decisionType === "AUTRE" && !data.otherDecision?.trim()) {
      context.addIssue({
        code: "custom",
        path: ["otherDecision"],
        message: "La décision doit être précisée.",
      });
    }

    if (data.decisionType === "MISE_A_PIED") {
      if (!data.suspensionDays || !data.suspensionStart || !data.suspensionEnd) {
        context.addIssue({
          code: "custom",
          path: ["suspensionDays"],
          message: "La durée et les dates de mise à pied sont obligatoires.",
        });
      }
    }
  });

export type ProcedureRequestInput = z.infer<
  typeof procedureRequestCreateSchema
>;
export type ProcedureFollowupInput = z.infer<typeof procedureFollowupSchema>;
