"use client";

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

type SectorEmailSetting = {
  id: number;
  name: string;
  emails: string[];
};

type RecipientOption = {
  cos: number | null;
  nom: string;
  prenom: string;
  email: string;
  actif: boolean;
};

type SectorEmailsResponse = {
  sectors?: SectorEmailSetting[];
  recipients?: RecipientOption[];
  message?: string;
};

function normalizeEmail(value: string) {
  return value.trim().toLowerCase();
}

function isValidEmail(value: string) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
}

export default function SectorEmailsPanel() {
  const [sectors, setSectors] = useState<SectorEmailSetting[]>([]);
  const [recipients, setRecipients] = useState<RecipientOption[]>([]);
  const [selectedSectorId, setSelectedSectorId] = useState<number | null>(null);
  const [selectedEmails, setSelectedEmails] = useState<string[]>([]);
  const [candidateEmails, setCandidateEmails] = useState<string[]>([]);
  const [emailsToRemove, setEmailsToRemove] = useState<string[]>([]);
  const [search, setSearch] = useState("");
  const [manualEmail, setManualEmail] = useState("");
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [testing, setTesting] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);

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

    async function loadSettings() {
      const token = localStorage.getItem("token");

      if (!token) return;

      setLoading(true);
      setError(null);

      try {
        const response = await fetch(
          `${process.env.NEXT_PUBLIC_API_URL}/api/admin/parametres/emails-secteurs`,
          {
            headers: {
              Authorization: `Bearer ${token}`,
            },
            cache: "no-store",
          },
        );

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

        if (!response.ok) {
          throw new Error(
            data?.message ?? "Impossible de charger les emails par secteur.",
          );
        }

        if (cancelled) return;

        const loadedSectors = data?.sectors ?? [];
        setSectors(loadedSectors);
        setRecipients(data?.recipients ?? []);

        const firstSector = loadedSectors[0];
        setSelectedSectorId(firstSector?.id ?? null);
        setSelectedEmails(firstSector?.emails ?? []);
      } catch (loadError) {
        if (!cancelled) {
          setError(
            loadError instanceof Error
              ? loadError.message
              : "Une erreur est survenue.",
          );
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    }

    void loadSettings();

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

  const selectedSector =
    sectors.find((sector) => sector.id === selectedSectorId) ?? null;

  const filteredRecipients = useMemo(() => {
    const normalizedSearch = search.trim().toLowerCase();
    const alreadySelected = new Set(selectedEmails);

    return recipients.filter((recipient) => {
      if (alreadySelected.has(recipient.email)) return false;

      if (!normalizedSearch) return true;

      return [recipient.nom, recipient.prenom, recipient.email]
        .join(" ")
        .toLowerCase()
        .includes(normalizedSearch);
    });
  }, [recipients, search, selectedEmails]);

  const hasUnsavedChanges =
    [...selectedEmails].sort().join(";") !==
    [...(selectedSector?.emails ?? [])].sort().join(";");

  function selectSector(id: number) {
    const sector = sectors.find((item) => item.id === id);

    setSelectedSectorId(id);
    setSelectedEmails(sector?.emails ?? []);
    setCandidateEmails([]);
    setEmailsToRemove([]);
    setManualEmail("");
    setError(null);
    setSuccess(null);
  }

  function addCandidateEmails() {
    if (candidateEmails.length === 0) return;

    setSelectedEmails((current) => [
      ...new Set([...current, ...candidateEmails]),
    ]);
    setCandidateEmails([]);
    setSuccess(null);
  }

  function removeSelectedEmails() {
    if (emailsToRemove.length === 0) return;

    const removed = new Set(emailsToRemove);
    setSelectedEmails((current) =>
      current.filter((email) => !removed.has(email)),
    );
    setEmailsToRemove([]);
    setSuccess(null);
  }

  function addManualEmail() {
    const email = normalizeEmail(manualEmail);

    if (!isValidEmail(email)) {
      setError("L’adresse email saisie est invalide.");
      return;
    }

    setSelectedEmails((current) => [...new Set([...current, email])]);
    setManualEmail("");
    setError(null);
    setSuccess(null);
  }

  async function saveSectorEmails() {
    if (!selectedSectorId || !selectedSector) return;

    const token = localStorage.getItem("token");

    if (!token) {
      setError("Session introuvable. Reconnecte-toi.");
      return;
    }

    setSaving(true);
    setError(null);
    setSuccess(null);

    try {
      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/api/admin/parametres/emails-secteurs`,
        {
          method: "PATCH",
          headers: {
            Authorization: `Bearer ${token}`,
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            sectorId: selectedSectorId,
            emails: selectedEmails,
          }),
        },
      );

      const data = (await response.json().catch(() => null)) as {
        message?: string;
        item?: SectorEmailSetting;
      } | null;

      if (!response.ok) {
        throw new Error(data?.message ?? "L’enregistrement a échoué.");
      }

      if (data?.item) {
        setSectors((current) =>
          current.map((sector) =>
            sector.id === data.item?.id ? data.item : sector,
          ),
        );
        setSelectedEmails(data.item.emails);
      }

      setSuccess(
        data?.message ??
          `Les destinataires de ${selectedSector.name} ont été enregistrés.`,
      );
    } catch (saveError) {
      setError(
        saveError instanceof Error
          ? saveError.message
          : "L’enregistrement a échoué.",
      );
    } finally {
      setSaving(false);
    }
  }

  async function sendSectorTestMail() {
    if (!selectedSectorId || !selectedSector) return;

    if (hasUnsavedChanges) {
      setError("Enregistre d’abord les destinataires avant de lancer le test.");
      return;
    }

    if (selectedEmails.length === 0) {
      setError("Ajoute au moins un destinataire avant de lancer le test.");
      return;
    }

    const confirmed = window.confirm(
      `Envoyer un mail entièrement fictif aux ${selectedEmails.length} destinataire(s) enregistrés pour « ${selectedSector.name} » ?`,
    );

    if (!confirmed) return;

    const token = localStorage.getItem("token");

    if (!token) {
      setError("Session introuvable. Reconnecte-toi.");
      return;
    }

    setTesting(true);
    setError(null);
    setSuccess(null);

    try {
      const response = await fetch(
        `${process.env.NEXT_PUBLIC_API_URL}/api/admin/parametres/emails-secteurs/test`,
        {
          method: "POST",
          headers: {
            Authorization: `Bearer ${token}`,
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            sectorId: selectedSectorId,
            confirmation: "ENVOYER_TEST_SECTEUR",
          }),
        },
      );

      const data = (await response.json().catch(() => null)) as {
        message?: string;
      } | null;

      if (!response.ok) {
        throw new Error(data?.message ?? "L’envoi du test a échoué.");
      }

      setSuccess(data?.message ?? "Le mail fictif a été envoyé.");
    } catch (testError) {
      setError(
        testError instanceof Error
          ? testError.message
          : "L’envoi du test a échoué.",
      );
    } finally {
      setTesting(false);
    }
  }

  if (loading) {
    return (
      <section className="rounded-lg bg-white p-8 text-center shadow">
        <p className="text-slate-500">Chargement des emails par secteur...</p>
      </section>
    );
  }

  return (
    <section className="rounded-lg bg-white p-4 shadow">
      <div className="mb-4">
        <h2 className="text-xl font-bold">Emails par secteur</h2>
        <p className="text-sm text-slate-500">
          Choisis les personnes qui recevront les alertes liées à chaque
          secteur. Le bouton de test utilise uniquement un contenu fictif et
          reste limité aux adresses autorisées par le serveur.
        </p>
      </div>

      {error && (
        <p className="mb-3 rounded bg-red-50 p-3 text-sm font-medium text-red-700">
          {error}
        </p>
      )}

      {success && (
        <p className="mb-3 rounded bg-green-50 p-3 text-sm font-medium text-green-700">
          {success}
        </p>
      )}

      <div className="grid gap-4 lg:grid-cols-[260px_1fr_80px_1fr]">
        <div>
          <h3 className="mb-2 font-semibold text-blue-700">Secteur concerné</h3>
          <div className="max-h-[430px] overflow-y-auto rounded border">
            {sectors.map((sector) => (
              <button
                key={sector.id}
                type="button"
                onClick={() => selectSector(sector.id)}
                className={`block w-full border-b px-3 py-2 text-left text-sm last:border-b-0 ${
                  selectedSectorId === sector.id
                    ? "bg-blue-600 font-semibold text-white"
                    : "bg-white hover:bg-blue-50"
                }`}
              >
                {sector.name}
                <span className="ml-2 text-xs opacity-70">
                  ({sector.emails.length})
                </span>
              </button>
            ))}
          </div>
        </div>

        <div>
          <h3 className="mb-2 font-semibold text-blue-700">
            Adresses enregistrées dans la base
          </h3>
          <input
            type="search"
            value={search}
            onChange={(event) => setSearch(event.target.value)}
            placeholder="Rechercher une personne ou une adresse..."
            className="mb-2 w-full rounded border border-slate-300 px-3 py-2 text-sm"
          />
          <select
            multiple
            value={candidateEmails}
            onChange={(event) =>
              setCandidateEmails(
                Array.from(
                  event.currentTarget.selectedOptions,
                  (option) => option.value,
                ),
              )
            }
            className="h-[330px] w-full rounded border border-slate-300 bg-white p-2 text-sm"
          >
            {filteredRecipients.map((recipient) => (
              <option key={recipient.email} value={recipient.email}>
                {recipient.nom} {recipient.prenom} — {recipient.email}
                {!recipient.actif ? " (inactif)" : ""}
              </option>
            ))}
          </select>
        </div>

        <div className="flex items-center justify-center">
          <div className="flex gap-2 lg:flex-col">
            <button
              type="button"
              onClick={addCandidateEmails}
              disabled={candidateEmails.length === 0}
              title="Ajouter les adresses sélectionnées"
              className="rounded bg-blue-600 px-4 py-2 font-bold text-white hover:bg-blue-700 disabled:opacity-40"
            >
              <span className="hidden lg:inline">→</span>
              <span className="lg:hidden">Ajouter</span>
            </button>
            <button
              type="button"
              onClick={removeSelectedEmails}
              disabled={emailsToRemove.length === 0}
              title="Retirer les adresses sélectionnées"
              className="rounded border border-red-400 bg-white px-4 py-2 font-bold text-red-600 hover:bg-red-50 disabled:opacity-40"
            >
              <span className="hidden lg:inline">←</span>
              <span className="lg:hidden">Retirer</span>
            </button>
          </div>
        </div>

        <div>
          <h3 className="mb-2 font-semibold text-blue-700">
            Destinataires choisis
          </h3>
          <select
            multiple
            value={emailsToRemove}
            onChange={(event) =>
              setEmailsToRemove(
                Array.from(
                  event.currentTarget.selectedOptions,
                  (option) => option.value,
                ),
              )
            }
            className="h-[280px] w-full rounded border border-slate-300 bg-white p-2 text-sm"
          >
            {selectedEmails.map((email) => (
              <option key={email} value={email}>
                {email}
              </option>
            ))}
          </select>

          <div className="mt-2 flex gap-2">
            <input
              type="email"
              value={manualEmail}
              onChange={(event) => setManualEmail(event.target.value)}
              onKeyDown={(event) => {
                if (event.key === "Enter") {
                  event.preventDefault();
                  addManualEmail();
                }
              }}
              placeholder="Ajouter une adresse manuellement"
              className="min-w-0 flex-1 rounded border border-slate-300 px-3 py-2 text-sm"
            />
            <button
              type="button"
              onClick={addManualEmail}
              className="rounded border border-blue-500 px-3 py-2 font-semibold text-blue-600 hover:bg-blue-50"
            >
              Ajouter
            </button>
          </div>

          <div className="mt-3 flex flex-wrap items-center justify-between gap-3">
            <span className="text-xs text-slate-500">
              {selectedEmails.length} destinataire(s)
            </span>
            <div className="flex gap-2">
              <button
                type="button"
                onClick={() => void sendSectorTestMail()}
                disabled={
                  testing ||
                  saving ||
                  !selectedSectorId ||
                  selectedEmails.length === 0 ||
                  hasUnsavedChanges
                }
                title={
                  hasUnsavedChanges
                    ? "Enregistre les modifications avant le test"
                    : "Envoyer un contenu fictif aux destinataires autorisés"
                }
                className="rounded bg-amber-500 px-4 py-2 font-semibold text-white hover:bg-amber-600 disabled:opacity-50"
              >
                {testing ? "Envoi du test..." : "Tester ce secteur"}
              </button>
              <button
                type="button"
                onClick={() => void saveSectorEmails()}
                disabled={saving || testing || !selectedSectorId}
                className="rounded bg-green-600 px-4 py-2 font-semibold text-white hover:bg-green-700 disabled:opacity-50"
              >
                {saving ? "Enregistrement..." : "Enregistrer"}
              </button>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}
