"use client";

import { type FormEvent, useEffect, useMemo, useState } from "react";

import type { Salarie } from "@/types/type";

type Props = {
  salarie: Salarie | null;
  currentUsername: string;
  canWrite: boolean;
};

const REQUEST_TYPES = [
  ["DEMANDE_NOUVELLES", "Demande de nouvelles"],
  ["LETTRE_RECADRAGE", "Lettre de recadrage"],
  ["AVERTISSEMENT_DIRECT", "Avertissement direct"],
  ["CONVOCATION_SANCTION", "Convocation entretien préalable à une sanction"],
  [
    "CONVOCATION_LICENCIEMENT_RUPTURE",
    "Convocation entretien préalable à un licenciement ou rupture anticipée du contrat",
  ],
  ["AUTRE", "Autre"],
] as const;

const FOLLOWUP_TYPES = new Set([
  "CONVOCATION_SANCTION",
  "CONVOCATION_LICENCIEMENT_RUPTURE",
]);

const DECISION_TYPES = [
  ["LETTRE_RECADRAGE", "Lettre de recadrage"],
  ["AVERTISSEMENT", "Avertissement"],
  ["MISE_A_PIED", "Mise à pied"],
  ["MUTATION_DISCIPLINAIRE", "Mutation disciplinaire (changement de poste)"],
  ["RETROGRADATION", "Rétrogradation"],
  ["LICENCIEMENT_CAUSE_REELLE_SERIEUSE", "Licenciement pour cause réelle et sérieuse"],
  ["LICENCIEMENT_RUPTURE_FAUTE_GRAVE", "Licenciement ou rupture anticipée pour faute grave"],
  ["LICENCIEMENT_RUPTURE_FAUTE_LOURDE", "Licenciement ou rupture anticipée pour faute lourde"],
  ["LICENCIEMENT_RUPTURE_INAPTITUDE", "Licenciement ou rupture anticipée pour inaptitude"],
  ["AUTRE", "Autre"],
] as const;

type RequestType = (typeof REQUEST_TYPES)[number][0];
type DecisionType = (typeof DECISION_TYPES)[number][0];

type HistoryItem = {
  id: number;
  action: string;
  summary: string | null;
  created_at: string;
  created_by: { username: string };
};

type ProcedureFollowup = {
  interview_at: string | null;
  interviewer_name: string | null;
  employee_present: boolean | null;
  accompanied_by: string | null;
  decision_type: DecisionType | null;
  other_decision: string | null;
  suspension_days: number | null;
  suspension_start: string | null;
  suspension_end: string | null;
  decision_reasons: string | null;
  facts_acknowledged: boolean | null;
  employee_statement: string | null;
  decision_maker_name: string | null;
  hr_validation_sent_at: string | null;
  notification_sent_at: string | null;
};

type ProcedureItem = {
  id: number;
  employee_cos: number;
  manager_name: string;
  request_type: RequestType;
  other_type: string | null;
  facts_date: string | null;
  facts_time: string | null;
  observed_by: string | null;
  facts_location: string | null;
  facts_description: string;
  witnesses: string | null;
  written_statements: boolean | null;
  status: string;
  created_at: string;
  updated_at: string;
  followup: ProcedureFollowup | null;
  history: HistoryItem[];
};

type EmailAddress = {
  address: string;
  kind: "professionnelle" | "personnelle";
};

type HrRecipient = {
  id: number;
  label: string;
  email: string;
};

type EmailHistoryItem = {
  id: number;
  recipient: string;
  subject: string | null;
  procedure_request_id: number | null;
  attachment_name: string | null;
  status: "PROCESSING" | "SENT" | "FAILED";
  created_at: string;
  sent_at: string | null;
  sent_by: { username: string; email: string | null };
};

type EmailProcedure = {
  id: number;
  request_type: RequestType;
  created_at: string;
};

type EmailData = {
  employee: { name: string; emails: EmailAddress[] };
  items: EmailHistoryItem[];
  procedures: EmailProcedure[];
  signature: {
    enabled: boolean;
    displayName: string;
    jobTitle: string;
  };
};

type RequestForm = {
  managerName: string;
  requestType: RequestType;
  otherType: string;
  factsDate: string;
  factsTime: string;
  observedBy: string;
  factsLocation: string;
  factsDescription: string;
  witnesses: string;
  writtenStatements: boolean | null;
};

type FollowupForm = {
  interviewAt: string;
  interviewerName: string;
  employeePresent: boolean | null;
  accompaniedBy: string;
  decisionType: DecisionType | "";
  otherDecision: string;
  suspensionDays: string;
  suspensionStart: string;
  suspensionEnd: string;
  decisionReasons: string;
  factsAcknowledged: boolean | null;
  employeeStatement: string;
  decisionMakerName: string;
  hrValidationSentAt: string;
  notificationSentAt: string;
};

function today() {
  const date = new Date();
  const offset = date.getTimezoneOffset() * 60_000;
  return new Date(date.getTime() - offset).toISOString().slice(0, 10);
}

function emptyRequest(managerName: string): RequestForm {
  return {
    managerName,
    requestType: "DEMANDE_NOUVELLES",
    otherType: "",
    factsDate: today(),
    factsTime: "",
    observedBy: managerName,
    factsLocation: "",
    factsDescription: "",
    witnesses: "",
    writtenStatements: null,
  };
}

function emptyFollowup(managerName: string): FollowupForm {
  return {
    interviewAt: "",
    interviewerName: managerName,
    employeePresent: null,
    accompaniedBy: "",
    decisionType: "",
    otherDecision: "",
    suspensionDays: "",
    suspensionStart: "",
    suspensionEnd: "",
    decisionReasons: "",
    factsAcknowledged: null,
    employeeStatement: "",
    decisionMakerName: managerName,
    hrValidationSentAt: "",
    notificationSentAt: "",
  };
}

function dateInput(value: string | null | undefined) {
  return value?.slice(0, 10) ?? "";
}

function dateTimeInput(value: string | null | undefined) {
  if (!value) return "";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value.slice(0, 16);
  const offset = date.getTimezoneOffset() * 60_000;
  return new Date(date.getTime() - offset).toISOString().slice(0, 16);
}

function formFromItem(item: ProcedureItem): RequestForm {
  return {
    managerName: item.manager_name,
    requestType: item.request_type,
    otherType: item.other_type ?? "",
    factsDate: dateInput(item.facts_date),
    factsTime: item.facts_time ?? "",
    observedBy: item.observed_by ?? "",
    factsLocation: item.facts_location ?? "",
    factsDescription: item.facts_description,
    witnesses: item.witnesses ?? "",
    writtenStatements: item.written_statements,
  };
}

function followupFromItem(item: ProcedureItem, managerName: string): FollowupForm {
  const value = item.followup;
  if (!value) return emptyFollowup(managerName);
  return {
    interviewAt: dateTimeInput(value.interview_at),
    interviewerName: value.interviewer_name ?? "",
    employeePresent: value.employee_present,
    accompaniedBy: value.accompanied_by ?? "",
    decisionType: value.decision_type ?? "",
    otherDecision: value.other_decision ?? "",
    suspensionDays: value.suspension_days?.toString() ?? "",
    suspensionStart: dateInput(value.suspension_start),
    suspensionEnd: dateInput(value.suspension_end),
    decisionReasons: value.decision_reasons ?? "",
    factsAcknowledged: value.facts_acknowledged,
    employeeStatement: value.employee_statement ?? "",
    decisionMakerName: value.decision_maker_name ?? managerName,
    hrValidationSentAt: dateTimeInput(value.hr_validation_sent_at),
    notificationSentAt: dateTimeInput(value.notification_sent_at),
  };
}

function requestLabel(value: string) {
  return REQUEST_TYPES.find(([key]) => key === value)?.[1] ?? value;
}

function statusLabel(value: string) {
  return value === "SUITE_COMPLETEE" ? "Suite complétée" : "Enregistrée";
}

export default function AutresTab({ salarie, currentUsername, canWrite }: Props) {
  const [activeAction, setActiveAction] = useState<"procedures" | "email">("procedures");
  const [items, setItems] = useState<ProcedureItem[]>([]);
  const [selected, setSelected] = useState<ProcedureItem | null>(null);
  const [requestForm, setRequestForm] = useState<RequestForm>(() =>
    emptyRequest(currentUsername),
  );
  const [followupForm, setFollowupForm] = useState<FollowupForm>(() =>
    emptyFollowup(currentUsername),
  );
  const [showRequest, setShowRequest] = useState(false);
  const [showFollowup, setShowFollowup] = useState(false);
  const [showHistory, setShowHistory] = useState(false);
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [emailData, setEmailData] = useState<EmailData | null>(null);
  const [emailRecipient, setEmailRecipient] = useState("");
  const [emailSubject, setEmailSubject] = useState("Information RH Connect");
  const [emailBody, setEmailBody] = useState("");
  const [emailProcedureId, setEmailProcedureId] = useState("");
  const [emailLoading, setEmailLoading] = useState(false);
  const [emailSending, setEmailSending] = useState(false);
  const [rhModalOpen, setRhModalOpen] = useState(false);
  const [rhRecipients, setRhRecipients] = useState<HrRecipient[]>([]);
  const [rhRecipientId, setRhRecipientId] = useState("");
  const [rhLoading, setRhLoading] = useState(false);
  const [rhSending, setRhSending] = useState(false);
  const [message, setMessage] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const supportsFollowup = useMemo(
    () => Boolean(selected && FOLLOWUP_TYPES.has(selected.request_type)),
    [selected],
  );

  function authHeaders(json = false): HeadersInit {
    return {
      ...(json ? { "Content-Type": "application/json" } : {}),
      Authorization: `Bearer ${localStorage.getItem("token")}`,
    };
  }

  async function refresh(preferredId?: number) {
    if (!salarie?.COS) {
      setItems([]);
      setSelected(null);
      return;
    }
    setLoading(true);
    setError(null);
    try {
      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/api/employes/${salarie.COS}/procedures`,
        { headers: authHeaders(), cache: "no-store" },
      );
      const data = await response.json().catch(() => null);
      if (!response.ok) throw new Error(data?.message ?? "Chargement impossible.");
      const nextItems: ProcedureItem[] = data.items ?? [];
      setItems(nextItems);
      if (preferredId) {
        const nextSelected = nextItems.find((item) => item.id === preferredId) ?? null;
        setSelected(nextSelected);
        if (nextSelected) {
          setRequestForm(formFromItem(nextSelected));
          setFollowupForm(followupFromItem(nextSelected, currentUsername));
        }
      }
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "Chargement impossible.");
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    setActiveAction("procedures");
    setSelected(null);
    setShowRequest(false);
    setShowFollowup(false);
    setShowHistory(false);
    setRequestForm(emptyRequest(currentUsername));
    setFollowupForm(emptyFollowup(currentUsername));
    setEmailData(null);
    setEmailRecipient("");
    setEmailSubject("Information RH Connect");
    setEmailBody(`Bonjour ${salarie?.PRE ?? ""},\n\n`);
    setEmailProcedureId("");
    setRhModalOpen(false);
    setRhRecipients([]);
    setRhRecipientId("");
    void refresh();
  }, [salarie?.COS, currentUsername]);

  function selectItem(item: ProcedureItem) {
    setSelected(item);
    setRequestForm(formFromItem(item));
    setFollowupForm(followupFromItem(item, currentUsername));
    setShowRequest(true);
    setShowFollowup(false);
    setShowHistory(false);
    setMessage(null);
    setError(null);
  }

  function startNew() {
    setSelected(null);
    setRequestForm(emptyRequest(currentUsername));
    setFollowupForm(emptyFollowup(currentUsername));
    setShowRequest(true);
    setShowFollowup(false);
    setShowHistory(false);
    setMessage(null);
    setError(null);
  }

  async function loadEmailData(resetForm = true) {
    if (!salarie?.COS || !canWrite) return;
    setEmailLoading(true);
    setError(null);
    try {
      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/api/employes/${salarie.COS}/communications`,
        { headers: authHeaders(), cache: "no-store" },
      );
      const data = await response.json().catch(() => null);
      if (!response.ok) throw new Error(data?.message ?? "Chargement des e-mails impossible.");
      const nextData = data as EmailData;
      setEmailData(nextData);
      if (resetForm) {
        setEmailRecipient(nextData.employee.emails[0]?.address ?? "");
        setEmailSubject("Information RH Connect");
        setEmailBody(`Bonjour ${salarie.PRE ?? ""},\n\n`);
        setEmailProcedureId("");
      }
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "Chargement des e-mails impossible.");
    } finally {
      setEmailLoading(false);
    }
  }

  function openProcedures() {
    setActiveAction("procedures");
    setMessage(null);
    setError(null);
  }

  function openEmail() {
    if (!canWrite) return;
    setActiveAction("email");
    setMessage(null);
    setError(null);
    void loadEmailData(true);
  }

  async function sendEmail(event: FormEvent) {
    event.preventDefault();
    if (!salarie?.COS || !canWrite || emailSending) return;
    if (!window.confirm(`Envoyer cet e-mail à ${emailRecipient} ?`)) return;

    setEmailSending(true);
    setMessage(null);
    setError(null);
    try {
      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/api/employes/${salarie.COS}/communications`,
        {
          method: "POST",
          headers: authHeaders(true),
          body: JSON.stringify({
            recipient: emailRecipient,
            subject: emailSubject,
            bodyText: emailBody,
            procedureId: emailProcedureId ? Number(emailProcedureId) : null,
          }),
        },
      );
      const data = await response.json().catch(() => null);
      if (!response.ok) throw new Error(data?.message ?? "Envoi impossible.");
      setMessage(data?.message ?? "L’e-mail a été envoyé.");
      await loadEmailData(false);
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "Envoi impossible.");
      await loadEmailData(false);
    } finally {
      setEmailSending(false);
    }
  }

  async function saveRequest(event: FormEvent) {
    event.preventDefault();
    if (!salarie?.COS || saving || !canWrite) return;
    setSaving(true);
    setMessage(null);
    setError(null);
    try {
      const response = await fetch(
        selected
          ? `${process.env.NEXT_PUBLIC_API_URL}/api/procedures/${selected.id}`
          : `${process.env.NEXT_PUBLIC_API_URL}/api/employes/${salarie.COS}/procedures`,
        {
          method: selected ? "PUT" : "POST",
          headers: authHeaders(true),
          body: JSON.stringify(requestForm),
        },
      );
      const data = await response.json().catch(() => null);
      if (!response.ok) throw new Error(data?.message ?? "Enregistrement impossible.");
      setMessage(selected ? "La demande a été modifiée." : "La demande a été enregistrée.");
      await refresh(data.item.id);
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "Enregistrement impossible.");
    } finally {
      setSaving(false);
    }
  }

  async function saveFollowup(event: FormEvent) {
    event.preventDefault();
    if (!selected || saving || !canWrite) return;
    setSaving(true);
    setMessage(null);
    setError(null);
    try {
      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/api/procedures/${selected.id}/suite`,
        {
          method: "PUT",
          headers: authHeaders(true),
          body: JSON.stringify({
            ...followupForm,
            suspensionDays: followupForm.suspensionDays
              ? Number(followupForm.suspensionDays)
              : null,
          }),
        },
      );
      const data = await response.json().catch(() => null);
      if (!response.ok) throw new Error(data?.message ?? "Enregistrement impossible.");
      setMessage("La suite de procédure a été enregistrée.");
      await refresh(selected.id);
      setShowFollowup(true);
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "Enregistrement impossible.");
    } finally {
      setSaving(false);
    }
  }

  async function downloadPdf() {
    if (!selected) return;
    setError(null);
    try {
      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/api/procedures/${selected.id}/pdf`,
        { headers: authHeaders() },
      );
      if (!response.ok) {
        const data = await response.json().catch(() => null);
        throw new Error(data?.message ?? "Téléchargement impossible.");
      }
      const blob = await response.blob();
      const url = URL.createObjectURL(blob);
      const anchor = document.createElement("a");
      anchor.href = url;
      anchor.download = `demande-procedure-${salarie?.NSA ?? selected.employee_cos}-${selected.id}.pdf`;
      document.body.appendChild(anchor);
      anchor.click();
      anchor.remove();
      URL.revokeObjectURL(url);
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "Téléchargement impossible.");
    }
  }

  async function openRhSend() {
    if (!selected || !canWrite) return;
    setRhModalOpen(true);
    setRhLoading(true);
    setMessage(null);
    setError(null);
    try {
      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/api/procedures/rh-recipients`,
        { headers: authHeaders(), cache: "no-store" },
      );
      const data = await response.json().catch(() => null);
      if (!response.ok) {
        throw new Error(data?.message ?? "Chargement des responsables RH impossible.");
      }
      const recipients = (data?.items ?? []) as HrRecipient[];
      setRhRecipients(recipients);
      setRhRecipientId((current) =>
        recipients.some((recipient) => String(recipient.id) === current)
          ? current
          : recipients[0]
            ? String(recipients[0].id)
            : "",
      );
    } catch (caught) {
      setError(
        caught instanceof Error
          ? caught.message
          : "Chargement des responsables RH impossible.",
      );
    } finally {
      setRhLoading(false);
    }
  }

  async function sendSelectedToRh() {
    if (!selected || !canWrite || !rhRecipientId || rhSending) return;
    const recipient = rhRecipients.find(
      (item) => item.id === Number(rhRecipientId),
    );
    if (!recipient) return;
    if (
      !window.confirm(
        `Envoyer la demande n°${selected.id} et son PDF à ${recipient.label} (${recipient.email}) ?`,
      )
    ) {
      return;
    }

    setRhSending(true);
    setMessage(null);
    setError(null);
    try {
      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/api/procedures/${selected.id}/send-to-hr`,
        {
          method: "POST",
          headers: authHeaders(true),
          body: JSON.stringify({ recipientId: Number(rhRecipientId) }),
        },
      );
      const data = await response.json().catch(() => null);
      if (!response.ok) {
        throw new Error(data?.message ?? "Envoi au responsable RH impossible.");
      }
      setRhModalOpen(false);
      setMessage(data?.message ?? `La demande a été envoyée à ${recipient.email}.`);
      await refresh(selected.id);
    } catch (caught) {
      setError(
        caught instanceof Error
          ? caught.message
          : "Envoi au responsable RH impossible.",
      );
    } finally {
      setRhSending(false);
    }
  }

  if (!salarie) {
    return <p className="rounded bg-amber-50 p-4 text-sm text-amber-800">Salarié introuvable.</p>;
  }

  return (
    <section className="grid h-full min-h-0 grid-cols-[190px_1fr] gap-3 overflow-hidden text-sm text-slate-900">
      <aside className="rounded border border-slate-200 bg-slate-50 p-3">
        <h2 className="mb-3 font-bold text-slate-800">Autres actions</h2>
        <button
          type="button"
          onClick={openProcedures}
          className={`w-full rounded px-3 py-3 text-left font-semibold ${activeAction === "procedures" ? "bg-sky-700 text-white" : "border bg-white text-slate-700"}`}
        >
          Demande de procédure
        </button>
        <button
          type="button"
          onClick={openEmail}
          disabled={!canWrite}
          className={`mt-2 w-full rounded px-3 py-3 text-left font-semibold disabled:cursor-not-allowed disabled:border disabled:bg-white disabled:text-slate-400 ${activeAction === "email" ? "bg-sky-700 text-white" : "border bg-white text-slate-700"}`}
        >
          Envoyer un e-mail
          {!canWrite && <span className="block text-xs font-normal">Droit d’écriture requis</span>}
        </button>
        <button type="button" disabled className="mt-2 w-full rounded border bg-white px-3 py-3 text-left text-slate-400">
          Envoyer un SMS <span className="block text-xs">Bientôt disponible</span>
        </button>
      </aside>

      {activeAction === "email" ? (
        <div className="min-h-0 overflow-y-auto rounded border border-slate-200 bg-white p-4">
          <div className="border-b pb-3">
            <h2 className="text-lg font-bold text-blue-700">Envoyer un e-mail</h2>
            <p className="text-xs text-slate-500">
              {salarie.TIT} {salarie.NSA} {salarie.PRE} — COS {salarie.COS}
            </p>
          </div>

          {message && <p className="mt-3 rounded border border-emerald-300 bg-emerald-50 p-2 text-emerald-800">{message}</p>}
          {error && <p role="alert" className="mt-3 rounded border border-red-300 bg-red-50 p-2 text-red-700">{error}</p>}

          {emailLoading ? (
            <p className="mt-4 text-slate-500">Chargement…</p>
          ) : emailData && emailData.employee.emails.length === 0 ? (
            <p className="mt-4 rounded border border-amber-300 bg-amber-50 p-3 text-amber-800">
              Aucune adresse e-mail personnelle ou professionnelle n’est renseignée pour ce salarié.
            </p>
          ) : (
            <form onSubmit={sendEmail} className="mt-4 rounded border border-blue-200 bg-blue-50/40 p-4">
              <div className="grid grid-cols-2 gap-3">
                <label className="col-span-2">
                  <span className="mb-1 block font-semibold">Destinataire *</span>
                  <select required value={emailRecipient} onChange={(event) => setEmailRecipient(event.target.value)} className="w-full rounded border bg-white px-3 py-2">
                    {(emailData?.employee.emails ?? []).map((email) => (
                      <option key={email.address} value={email.address}>
                        {email.address} — adresse {email.kind}
                      </option>
                    ))}
                  </select>
                </label>
                <label className="col-span-2">
                  <span className="mb-1 block font-semibold">Objet *</span>
                  <input required maxLength={255} value={emailSubject} onChange={(event) => setEmailSubject(event.target.value)} className="w-full rounded border bg-white px-3 py-2" />
                </label>
                <label className="col-span-2">
                  <span className="mb-1 block font-semibold">Message *</span>
                  <textarea required maxLength={20000} rows={12} value={emailBody} onChange={(event) => setEmailBody(event.target.value)} className="w-full rounded border bg-white px-3 py-2" />
                </label>
                <div className={`col-span-2 rounded border p-3 text-sm ${emailData?.signature.enabled ? "border-emerald-300 bg-emerald-50 text-emerald-800" : "border-amber-300 bg-amber-50 text-amber-800"}`}>
                  {emailData?.signature.enabled ? (
                    <>
                      La signature de <strong>{emailData.signature.displayName}</strong>
                      {emailData.signature.jobTitle ? ` — ${emailData.signature.jobTitle}` : ""} sera ajoutée automatiquement après le message.
                    </>
                  ) : (
                    <>Aucune signature automatique n’est configurée pour votre compte. Un super-administrateur peut la renseigner dans les paramètres.</>
                  )}
                </div>
                <div className="col-span-2 rounded border border-slate-300 bg-slate-50 p-3 text-sm text-slate-600">
                  Un avertissement indiquant que le message a été envoyé automatiquement et qu’il ne faut pas y répondre sera ajouté par RH Connect. Cet avertissement n’est pas modifiable.
                </div>
                <label className="col-span-2">
                  <span className="mb-1 block font-semibold">Pièce jointe facultative</span>
                  <select value={emailProcedureId} onChange={(event) => setEmailProcedureId(event.target.value)} className="w-full rounded border bg-white px-3 py-2">
                    <option value="">Aucune pièce jointe</option>
                    {(emailData?.procedures ?? []).map((procedure) => (
                      <option key={procedure.id} value={procedure.id}>
                        Demande n°{procedure.id} — {requestLabel(procedure.request_type)} — {new Date(procedure.created_at).toLocaleDateString("fr-FR")}
                      </option>
                    ))}
                  </select>
                  <span className="mt-1 block text-xs text-slate-500">Le PDF est régénéré au moment de l’envoi avec les dernières informations enregistrées.</span>
                </label>
              </div>
              <div className="mt-4 flex justify-end">
                <button type="submit" disabled={emailSending || !emailRecipient} className="rounded bg-green-600 px-5 py-2 font-semibold text-white disabled:opacity-50">
                  {emailSending ? "Envoi en cours…" : "Envoyer l’e-mail"}
                </button>
              </div>
            </form>
          )}

          <div className="mt-5 overflow-hidden rounded border">
            <div className="grid grid-cols-[150px_1fr_1fr_110px] bg-slate-100 px-3 py-2 text-xs font-semibold">
              <span>Date</span><span>Destinataire</span><span>Objet</span><span>Statut</span>
            </div>
            {!emailLoading && (emailData?.items.length ?? 0) === 0 ? (
              <p className="p-3 text-slate-500">Aucun e-mail envoyé à ce salarié.</p>
            ) : (emailData?.items ?? []).map((item) => (
              <div key={item.id} className="grid grid-cols-[150px_1fr_1fr_110px] border-t px-3 py-2 text-xs">
                <span>{new Date(item.sent_at ?? item.created_at).toLocaleString("fr-FR")}</span>
                <span className="truncate" title={item.recipient}>{item.recipient}</span>
                <span className="truncate" title={item.subject ?? ""}>{item.subject}</span>
                <span className={item.status === "SENT" ? "font-semibold text-emerald-700" : item.status === "FAILED" ? "font-semibold text-red-700" : "text-amber-700"}>
                  {item.status === "SENT" ? "Envoyé" : item.status === "FAILED" ? "Échec" : "En cours"}
                </span>
              </div>
            ))}
          </div>
        </div>
      ) : (
      <div className="min-h-0 overflow-y-auto rounded border border-slate-200 bg-white p-4">
        <div className="flex flex-wrap items-center justify-between gap-2 border-b pb-3">
          <div>
            <h2 className="text-lg font-bold text-blue-700">Demandes de procédure</h2>
            <p className="text-xs text-slate-500">{salarie.TIT} {salarie.NSA} {salarie.PRE} — COS {salarie.COS}</p>
          </div>
          {canWrite && (
            <button type="button" onClick={startNew} className="rounded bg-blue-600 px-4 py-2 font-semibold text-white hover:bg-blue-700">
              Nouvelle demande
            </button>
          )}
        </div>

        {message && <p className="mt-3 rounded border border-emerald-300 bg-emerald-50 p-2 text-emerald-800">{message}</p>}
        {error && <p role="alert" className="mt-3 rounded border border-red-300 bg-red-50 p-2 text-red-700">{error}</p>}

        <div className="mt-4 overflow-hidden rounded border">
          <div className="grid grid-cols-[100px_1fr_130px_120px] bg-slate-100 px-3 py-2 text-xs font-semibold">
            <span>Date</span><span>Type</span><span>Statut</span><span>Responsable</span>
          </div>
          {loading ? (
            <p className="p-3 text-slate-500">Chargement…</p>
          ) : items.length === 0 ? (
            <p className="p-3 text-slate-500">Aucune demande enregistrée pour ce salarié.</p>
          ) : items.map((item) => (
            <button key={item.id} type="button" onClick={() => selectItem(item)} className={`grid w-full grid-cols-[100px_1fr_130px_120px] border-t px-3 py-2 text-left text-xs hover:bg-blue-50 ${selected?.id === item.id ? "bg-blue-50" : ""}`}>
              <span>{new Date(item.created_at).toLocaleDateString("fr-FR")}</span>
              <span className="font-semibold">{requestLabel(item.request_type)}</span>
              <span>{statusLabel(item.status)}</span>
              <span className="truncate">{item.manager_name}</span>
            </button>
          ))}
        </div>

        {showRequest && (
          <form onSubmit={saveRequest} className="mt-4 rounded border border-blue-200 bg-blue-50/40 p-4">
            <div className="mb-4 flex flex-wrap items-center justify-between gap-2">
              <h3 className="font-bold text-blue-800">{selected ? `Demande n°${selected.id}` : "Nouvelle demande"}</h3>
              {selected && (
                <div className="flex flex-wrap gap-2">
                  <button type="button" onClick={() => void downloadPdf()} className="rounded bg-slate-700 px-3 py-2 text-xs font-semibold text-white">Télécharger le PDF</button>
                  <button type="button" onClick={() => void openRhSend()} disabled={!canWrite || rhSending} className="rounded bg-emerald-600 px-3 py-2 text-xs font-semibold text-white hover:bg-emerald-700 disabled:cursor-not-allowed disabled:opacity-50">Envoyer au responsable RH</button>
                  <button type="button" onClick={() => setShowHistory((value) => !value)} className="rounded border border-slate-400 bg-white px-3 py-2 text-xs font-semibold">Historique ({selected.history.length})</button>
                  {supportsFollowup && (
                    <button type="button" onClick={() => setShowFollowup((value) => !value)} className="rounded bg-violet-600 px-3 py-2 text-xs font-semibold text-white">
                      {selected.followup ? "Modifier la suite" : "Compléter la suite de procédure"}
                    </button>
                  )}
                </div>
              )}
            </div>

            {showHistory && selected && (
              <div className="mb-4 rounded border bg-white p-3">
                <h4 className="mb-2 font-semibold">Historique</h4>
                {selected.history.map((history) => (
                  <div key={history.id} className="border-t py-2 text-xs first:border-t-0">
                    <strong>{history.summary ?? history.action}</strong> — {history.created_by.username}, {new Date(history.created_at).toLocaleString("fr-FR")}
                  </div>
                ))}
              </div>
            )}

            <div className="grid grid-cols-2 gap-3">
              <label className="col-span-2"><span className="mb-1 block font-semibold">Responsable hiérarchique *</span><input required maxLength={255} value={requestForm.managerName} onChange={(event) => setRequestForm((value) => ({ ...value, managerName: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2 disabled:bg-slate-100" /></label>
              <fieldset className="col-span-2"><legend className="mb-2 font-semibold">Type de demande *</legend><div className="grid grid-cols-2 gap-2">{REQUEST_TYPES.map(([value, label]) => <label key={value} className={`flex cursor-pointer gap-2 rounded border p-2 ${requestForm.requestType === value ? "border-blue-500 bg-blue-50" : "bg-white"}`}><input type="radio" name="requestType" value={value} checked={requestForm.requestType === value} onChange={() => setRequestForm((form) => ({ ...form, requestType: value }))} disabled={!canWrite} /><span>{label}</span></label>)}</div></fieldset>
              {requestForm.requestType === "AUTRE" && <label className="col-span-2"><span className="mb-1 block font-semibold">Précisez la demande *</span><input required value={requestForm.otherType} onChange={(event) => setRequestForm((value) => ({ ...value, otherType: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>}
              <label><span className="mb-1 block font-semibold">Date des faits *</span><input required type="date" value={requestForm.factsDate} onChange={(event) => setRequestForm((value) => ({ ...value, factsDate: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <label><span className="mb-1 block font-semibold">Heure des faits *</span><input required type="time" value={requestForm.factsTime} onChange={(event) => setRequestForm((value) => ({ ...value, factsTime: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <label><span className="mb-1 block font-semibold">Personne ayant constaté les faits *</span><input required value={requestForm.observedBy} onChange={(event) => setRequestForm((value) => ({ ...value, observedBy: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <label><span className="mb-1 block font-semibold">Lieu des faits *</span><input required value={requestForm.factsLocation} onChange={(event) => setRequestForm((value) => ({ ...value, factsLocation: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <label className="col-span-2"><span className="mb-1 block font-semibold">Faits reprochés, motifs précis et exhaustifs *</span><textarea required minLength={10} rows={7} value={requestForm.factsDescription} onChange={(event) => setRequestForm((value) => ({ ...value, factsDescription: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <label className="col-span-2"><span className="mb-1 block font-semibold">Témoins des faits</span><textarea rows={3} value={requestForm.witnesses} onChange={(event) => setRequestForm((value) => ({ ...value, witnesses: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <fieldset className="col-span-2"><legend className="mb-1 font-semibold">Attestations écrites réalisées</legend><div className="flex gap-5"><label><input type="radio" name="written" checked={requestForm.writtenStatements === true} onChange={() => setRequestForm((value) => ({ ...value, writtenStatements: true }))} disabled={!canWrite} /> Oui</label><label><input type="radio" name="written" checked={requestForm.writtenStatements === false} onChange={() => setRequestForm((value) => ({ ...value, writtenStatements: false }))} disabled={!canWrite} /> Non</label><button type="button" onClick={() => setRequestForm((value) => ({ ...value, writtenStatements: null }))} disabled={!canWrite} className="text-xs text-blue-700">Non renseigné</button></div></fieldset>
            </div>
            {canWrite && <div className="mt-4 flex justify-end"><button disabled={saving} className="rounded bg-green-600 px-5 py-2 font-semibold text-white disabled:opacity-50">{saving ? "Enregistrement…" : selected ? "Enregistrer les modifications" : "Enregistrer la demande"}</button></div>}
          </form>
        )}

        {showFollowup && selected && supportsFollowup && (
          <form onSubmit={saveFollowup} className="mt-4 rounded border-2 border-violet-300 bg-violet-50/50 p-4">
            <h3 className="mb-4 text-base font-bold text-violet-800">Suite de procédure — après l’entretien</h3>
            <div className="grid grid-cols-2 gap-3">
              <label><span className="mb-1 block font-semibold">Date et heure de l’entretien *</span><input required type="datetime-local" value={followupForm.interviewAt} onChange={(event) => setFollowupForm((value) => ({ ...value, interviewAt: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <label><span className="mb-1 block font-semibold">Personne réalisant l’entretien *</span><input required value={followupForm.interviewerName} onChange={(event) => setFollowupForm((value) => ({ ...value, interviewerName: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <fieldset><legend className="mb-1 font-semibold">Salarié présent ? *</legend><div className="flex gap-5"><label><input required type="radio" name="present" checked={followupForm.employeePresent === true} onChange={() => setFollowupForm((value) => ({ ...value, employeePresent: true }))} disabled={!canWrite} /> Oui</label><label><input required type="radio" name="present" checked={followupForm.employeePresent === false} onChange={() => setFollowupForm((value) => ({ ...value, employeePresent: false }))} disabled={!canWrite} /> Non</label></div></fieldset>
              <label><span className="mb-1 block font-semibold">En présence de</span><input value={followupForm.accompaniedBy} onChange={(event) => setFollowupForm((value) => ({ ...value, accompaniedBy: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <label className="col-span-2"><span className="mb-1 block font-semibold">Décision *</span><select required value={followupForm.decisionType} onChange={(event) => setFollowupForm((value) => ({ ...value, decisionType: event.target.value as DecisionType }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2"><option value="">Sélectionner une décision</option>{DECISION_TYPES.map(([value, label]) => <option key={value} value={value}>{label}</option>)}</select></label>
              {followupForm.decisionType === "AUTRE" && <label className="col-span-2"><span className="mb-1 block font-semibold">Précisez la décision *</span><input required value={followupForm.otherDecision} onChange={(event) => setFollowupForm((value) => ({ ...value, otherDecision: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>}
              {followupForm.decisionType === "MISE_A_PIED" && <><label><span className="mb-1 block font-semibold">Nombre de jours (9 maximum) *</span><input required type="number" min={1} max={9} value={followupForm.suspensionDays} onChange={(event) => setFollowupForm((value) => ({ ...value, suspensionDays: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label><span /><label><span className="mb-1 block font-semibold">Du *</span><input required type="date" value={followupForm.suspensionStart} onChange={(event) => setFollowupForm((value) => ({ ...value, suspensionStart: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label><label><span className="mb-1 block font-semibold">Au *</span><input required type="date" min={followupForm.suspensionStart || undefined} value={followupForm.suspensionEnd} onChange={(event) => setFollowupForm((value) => ({ ...value, suspensionEnd: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label></>}
              <label className="col-span-2"><span className="mb-1 block font-semibold">Motifs de la décision *</span><textarea required minLength={10} rows={5} value={followupForm.decisionReasons} onChange={(event) => setFollowupForm((value) => ({ ...value, decisionReasons: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <fieldset><legend className="mb-1 font-semibold">Le salarié a reconnu les faits *</legend><div className="flex gap-5"><label><input required type="radio" name="acknowledged" checked={followupForm.factsAcknowledged === true} onChange={() => setFollowupForm((value) => ({ ...value, factsAcknowledged: true }))} disabled={!canWrite} /> Oui</label><label><input required type="radio" name="acknowledged" checked={followupForm.factsAcknowledged === false} onChange={() => setFollowupForm((value) => ({ ...value, factsAcknowledged: false }))} disabled={!canWrite} /> Non</label></div></fieldset>
              <label><span className="mb-1 block font-semibold">Décisionnaire *</span><input required value={followupForm.decisionMakerName} onChange={(event) => setFollowupForm((value) => ({ ...value, decisionMakerName: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <label className="col-span-2"><span className="mb-1 block font-semibold">Justification du salarié</span><textarea rows={4} value={followupForm.employeeStatement} onChange={(event) => setFollowupForm((value) => ({ ...value, employeeStatement: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <label><span className="mb-1 block font-semibold">Envoi DRH pour validation</span><input type="datetime-local" value={followupForm.hrValidationSentAt} onChange={(event) => setFollowupForm((value) => ({ ...value, hrValidationSentAt: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
              <label><span className="mb-1 block font-semibold">Notification envoyée/remise</span><input type="datetime-local" value={followupForm.notificationSentAt} onChange={(event) => setFollowupForm((value) => ({ ...value, notificationSentAt: event.target.value }))} disabled={!canWrite} className="w-full rounded border bg-white px-3 py-2" /></label>
            </div>
            {canWrite && <div className="mt-4 flex justify-end"><button disabled={saving} className="rounded bg-violet-600 px-5 py-2 font-semibold text-white disabled:opacity-50">{saving ? "Enregistrement…" : "Enregistrer la suite"}</button></div>}
          </form>
        )}

        {rhModalOpen && selected && (
          <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/45 p-4" role="dialog" aria-modal="true" aria-labelledby="rh-send-title">
            <div className="w-full max-w-lg rounded-lg bg-white p-5 shadow-xl">
              <div className="flex items-start justify-between gap-4 border-b pb-3">
                <div>
                  <h3 id="rh-send-title" className="text-lg font-bold text-slate-900">Envoyer au responsable RH</h3>
                  <p className="mt-1 text-xs text-slate-500">Demande n°{selected.id} — le PDF à jour sera joint automatiquement.</p>
                </div>
                <button type="button" onClick={() => setRhModalOpen(false)} disabled={rhSending} className="rounded px-2 py-1 text-xl leading-none text-slate-500 hover:bg-slate-100" aria-label="Fermer">×</button>
              </div>

              <div className="mt-4">
                <label htmlFor="rh-recipient" className="mb-1 block font-semibold">Responsable RH destinataire *</label>
                {rhLoading ? (
                  <p className="rounded border bg-slate-50 p-3 text-slate-500">Chargement des adresses…</p>
                ) : rhRecipients.length === 0 ? (
                  <p className="rounded border border-amber-300 bg-amber-50 p-3 text-amber-800">Aucune adresse RH active. Un super-administrateur doit en ajouter dans Paramètres généraux.</p>
                ) : (
                  <select id="rh-recipient" value={rhRecipientId} onChange={(event) => setRhRecipientId(event.target.value)} disabled={rhSending} className="w-full rounded border bg-white px-3 py-2">
                    {rhRecipients.map((recipient) => (
                      <option key={recipient.id} value={recipient.id}>{recipient.label} — {recipient.email}</option>
                    ))}
                  </select>
                )}
                <p className="mt-3 rounded border border-blue-200 bg-blue-50 p-3 text-xs text-blue-900">Le message, la mention de non-réponse et la signature du compte connecté seront ajoutés automatiquement. L’envoi sera conservé dans l’historique de la demande.</p>
              </div>

              <div className="mt-5 flex justify-end gap-2">
                <button type="button" onClick={() => setRhModalOpen(false)} disabled={rhSending} className="rounded border border-slate-300 bg-white px-4 py-2 font-semibold">Annuler</button>
                <button type="button" onClick={() => void sendSelectedToRh()} disabled={rhLoading || rhSending || !rhRecipientId} className="rounded bg-emerald-600 px-4 py-2 font-semibold text-white hover:bg-emerald-700 disabled:cursor-not-allowed disabled:opacity-50">{rhSending ? "Envoi…" : "Envoyer la demande"}</button>
              </div>
            </div>
          </div>
        )}
      </div>
      )}
    </section>
  );
}
