"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useRouter } from "next/navigation";

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

type MonthOption = {
  month: number;
};

type YearOption = {
  year: number;
  months: MonthOption[];
};

type EstablishmentOption = {
  establishment: string;
  years: YearOption[];
};

type Props = {
  salarie: Salarie | null;
  defaultEstablishment?: string | null;
};

function normalize(value: string | null | undefined) {
  return (value ?? "")
    .trim()
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toLocaleUpperCase("fr");
}

function monthLabel(month: number) {
  const label = new Intl.DateTimeFormat("fr-FR", { month: "long" }).format(
    new Date(2000, month - 1, 1),
  );

  return label.charAt(0).toLocaleUpperCase("fr") + label.slice(1);
}

export default function FichesPaieTab({
  salarie,
  defaultEstablishment,
}: Props) {
  const router = useRouter();
  const [options, setOptions] = useState<EstablishmentOption[]>([]);
  const [establishment, setEstablishment] = useState("");
  const [year, setYear] = useState("");
  const [month, setMonth] = useState("");
  const [loadingOptions, setLoadingOptions] = useState(true);
  const [loadingPdf, setLoadingPdf] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [pdfUrl, setPdfUrl] = useState<string | null>(null);
  const pdfUrlRef = useRef<string | null>(null);

  const establishmentOption = useMemo(
    () => options.find((item) => item.establishment === establishment),
    [options, establishment],
  );
  const yearOption = useMemo(
    () => establishmentOption?.years.find((item) => item.year === Number(year)),
    [establishmentOption, year],
  );

  const replacePdfUrl = useCallback((nextUrl: string | null) => {
    if (pdfUrlRef.current) URL.revokeObjectURL(pdfUrlRef.current);
    pdfUrlRef.current = nextUrl;
    setPdfUrl(nextUrl);
  }, []);

  useEffect(() => {
    return () => {
      if (pdfUrlRef.current) URL.revokeObjectURL(pdfUrlRef.current);
    };
  }, []);

  useEffect(() => {
    let cancelled = false;

    async function loadOptions() {
      setLoadingOptions(true);
      setError(null);

      try {
        const token = localStorage.getItem("token");
        const response = await fetch(
          `${process.env.NEXT_PUBLIC_API_URL}/api/fiches-paie/options`,
          {
            headers: { Authorization: `Bearer ${token}` },
            cache: "no-store",
          },
        );

        if (response.status === 401) {
          localStorage.removeItem("token");
          localStorage.removeItem("user");
          router.push("/login");
          return;
        }

        const data = await response.json().catch(() => null);

        if (!response.ok) {
          throw new Error(
            data?.message ?? "Impossible de charger les périodes disponibles.",
          );
        }

        if (cancelled) return;

        const items: EstablishmentOption[] = Array.isArray(data?.items)
          ? data.items
          : [];
        setOptions(items);

        const preferred =
          items.find(
            (item) =>
              normalize(item.establishment) === normalize(defaultEstablishment),
          ) ?? items[0];
        const preferredYear = preferred?.years[0];
        const preferredMonth = preferredYear?.months[0];

        setEstablishment(preferred?.establishment ?? "");
        setYear(preferredYear ? String(preferredYear.year) : "");
        setMonth(preferredMonth ? String(preferredMonth.month) : "");
      } catch (caughtError) {
        if (!cancelled) {
          setError(
            caughtError instanceof Error
              ? caughtError.message
              : "Une erreur inattendue est survenue.",
          );
        }
      } finally {
        if (!cancelled) setLoadingOptions(false);
      }
    }

    void loadOptions();

    return () => {
      cancelled = true;
    };
  }, [defaultEstablishment, router]);

  useEffect(() => {
    replacePdfUrl(null);
    setError(null);
  }, [salarie?.COS, establishment, year, month, replacePdfUrl]);

  function handleEstablishmentChange(value: string) {
    const nextEstablishment = options.find(
      (item) => item.establishment === value,
    );
    const nextYear = nextEstablishment?.years[0];
    const nextMonth = nextYear?.months[0];

    setEstablishment(value);
    setYear(nextYear ? String(nextYear.year) : "");
    setMonth(nextMonth ? String(nextMonth.month) : "");
  }

  function handleYearChange(value: string) {
    const nextYear = establishmentOption?.years.find(
      (item) => item.year === Number(value),
    );

    setYear(value);
    setMonth(nextYear?.months[0] ? String(nextYear.months[0].month) : "");
  }

  async function loadPayslip() {
    if (!salarie?.COS || !establishment || !year || !month) return;

    setLoadingPdf(true);
    setError(null);
    replacePdfUrl(null);

    try {
      const token = localStorage.getItem("token");
      const query = new URLSearchParams({
        etablissement: establishment,
        annee: year,
        mois: month,
      });
      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/api/fiches-paie/employe/${salarie.COS}?${query}`,
        {
          headers: { Authorization: `Bearer ${token}` },
          cache: "no-store",
        },
      );

      if (response.status === 401) {
        localStorage.removeItem("token");
        localStorage.removeItem("user");
        router.push("/login");
        return;
      }

      if (!response.ok) {
        const data = await response.json().catch(() => null);
        throw new Error(
          data?.message ?? "Impossible de consulter cette fiche de paie.",
        );
      }

      const blob = await response.blob();

      if (blob.type !== "application/pdf" || blob.size === 0) {
        throw new Error("Le serveur a renvoyé un document PDF invalide.");
      }

      replacePdfUrl(URL.createObjectURL(blob));
    } catch (caughtError) {
      setError(
        caughtError instanceof Error
          ? caughtError.message
          : "Une erreur inattendue est survenue.",
      );
    } finally {
      setLoadingPdf(false);
    }
  }

  const hasOptions = options.length > 0;
  const downloadName = `fiche-paie-${year}-${month.padStart(2, "0")}.pdf`;

  return (
    <section className="flex h-full min-h-0 flex-col overflow-hidden rounded border border-slate-200 bg-slate-50 p-4 text-slate-900">
      <div className="flex flex-wrap items-end gap-3 rounded bg-white p-3 shadow-sm">
        <label className="min-w-52 flex-1">
          <span className="mb-1 block text-xs font-semibold text-slate-600">
            Établissement
          </span>
          <select
            value={establishment}
            onChange={(event) => handleEstablishmentChange(event.target.value)}
            disabled={loadingOptions || !hasOptions}
            className="w-full rounded border border-slate-300 bg-white px-3 py-2 text-sm disabled:bg-slate-100"
          >
            {!hasOptions && <option value="">Aucun établissement</option>}
            {options.map((item) => (
              <option key={item.establishment} value={item.establishment}>
                {item.establishment}
              </option>
            ))}
          </select>
        </label>

        <label className="w-32">
          <span className="mb-1 block text-xs font-semibold text-slate-600">
            Année
          </span>
          <select
            value={year}
            onChange={(event) => handleYearChange(event.target.value)}
            disabled={!establishmentOption}
            className="w-full rounded border border-slate-300 bg-white px-3 py-2 text-sm disabled:bg-slate-100"
          >
            {establishmentOption?.years.map((item) => (
              <option key={item.year} value={item.year}>
                {item.year}
              </option>
            ))}
          </select>
        </label>

        <label className="w-40">
          <span className="mb-1 block text-xs font-semibold text-slate-600">
            Mois
          </span>
          <select
            value={month}
            onChange={(event) => setMonth(event.target.value)}
            disabled={!yearOption}
            className="w-full rounded border border-slate-300 bg-white px-3 py-2 text-sm disabled:bg-slate-100"
          >
            {yearOption?.months.map((item) => (
              <option key={item.month} value={item.month}>
                {monthLabel(item.month)}
              </option>
            ))}
          </select>
        </label>

        <button
          type="button"
          onClick={() => void loadPayslip()}
          disabled={
            loadingOptions ||
            loadingPdf ||
            !salarie?.COS ||
            !establishment ||
            !year ||
            !month
          }
          className="rounded bg-blue-600 px-5 py-2 text-sm font-semibold text-white shadow hover:bg-blue-700 disabled:cursor-not-allowed disabled:bg-blue-300"
        >
          {loadingPdf ? "Recherche..." : "Consulter"}
        </button>

        {pdfUrl && (
          <a
            href={pdfUrl}
            download={downloadName}
            className="rounded border border-blue-600 bg-white px-5 py-2 text-sm font-semibold text-blue-700 hover:bg-blue-50"
          >
            Télécharger
          </a>
        )}
      </div>

      {error && (
        <p
          role="alert"
          className="mt-3 rounded border border-red-300 bg-red-50 p-3 text-sm text-red-700"
        >
          {error}
        </p>
      )}

      {!loadingOptions && !hasOptions && !error && (
        <p className="mt-3 rounded border border-amber-300 bg-amber-50 p-3 text-sm text-amber-800">
          Aucun fichier de paie conforme n’est actuellement disponible.
        </p>
      )}

      <div className="mt-3 min-h-0 flex-1 overflow-hidden rounded border border-slate-300 bg-white">
        {pdfUrl ? (
          <iframe
            src={pdfUrl}
            title={`Fiche de paie de ${[salarie?.PRE, salarie?.NSA]
              .filter(Boolean)
              .join(" ")}`}
            className="h-full min-h-96 w-full"
          />
        ) : (
          <div className="flex h-full min-h-72 items-center justify-center p-6 text-center text-sm text-slate-500">
            Sélectionnez une période puis cliquez sur « Consulter ».
          </div>
        )}
      </div>
    </section>
  );
}
