'use client';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
  AlertCircle,
  ChevronLeft,
  ChevronRight,
  Loader2,
  Plus,
  RotateCcw,
  Search,
  UserCheck,
  Users as UsersIcon,
  UserX,
} from 'lucide-react';

import {
  extractApiErrorMessage,
  fetchMe,
  fetchUtilisateurs,
  type AuthUser,
  type FiltresUtilisateurs,
  type Utilisateur,
} from '@/lib/api';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Skeleton } from '@/components/ui/skeleton';
import { nomComplet } from '@/lib/utilisateurs';
import { cn } from '@/lib/utils';

import {
  UtilisateursList,
  type ColonneTri,
  type SensTri,
} from './utilisateurs-list';
import { CreateUtilisateurDialog } from './create-utilisateur-dialog';

const selectClassName =
  'flex h-10 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50';

const PAGE_SIZE_OPTIONS = [10, 25, 50, 100] as const;

const FILTRES_VIDES: Required<FiltresUtilisateurs> = {
  email: '',
  recherche: '',
  statut: '',
};

const comparateurTexte = new Intl.Collator('fr', { sensitivity: 'base' });

function comparer(
  a: Utilisateur,
  b: Utilisateur,
  colonne: ColonneTri,
): number {
  switch (colonne) {
    case 'email':
      return comparateurTexte.compare(a.email, b.email);
    case 'statut':
      // Les comptes actifs d'abord en tri ascendant.
      return Number(b.actif) - Number(a.actif);
    case 'created_at':
      return (
        new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
      );
    default:
      return comparateurTexte.compare(nomComplet(a), nomComplet(b));
  }
}

type IndicateurProps = {
  icone: typeof UsersIcon;
  libelle: string;
  valeur: number;
  accent?: 'neutre' | 'succes' | 'alerte';
};

function Indicateur({
  icone: Icone,
  libelle,
  valeur,
  accent = 'neutre',
}: IndicateurProps) {
  return (
    <div className="flex items-center gap-3 px-6 py-4">
      <div
        className={cn(
          'flex h-10 w-10 shrink-0 items-center justify-center rounded-lg',
          accent === 'succes' && 'bg-emerald-100 text-emerald-700',
          accent === 'alerte' && 'bg-destructive/10 text-destructive',
          accent === 'neutre' && 'bg-primary/10 text-primary',
        )}
      >
        <Icone className="h-5 w-5" />
      </div>
      <div>
        <p className="text-2xl font-semibold tabular-nums leading-none">
          {valeur}
        </p>
        <p className="mt-1 text-xs uppercase tracking-wide text-muted-foreground">
          {libelle}
        </p>
      </div>
    </div>
  );
}

export function UtilisateursPanel() {
  const [user, setUser] = useState<AuthUser | null>(null);
  const [utilisateurs, setUtilisateurs] = useState<Utilisateur[]>([]);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [createDialogOpen, setCreateDialogOpen] = useState(false);
  const [filtres, setFiltres] =
    useState<Required<FiltresUtilisateurs>>(FILTRES_VIDES);
  const [filtresAppliques, setFiltresAppliques] =
    useState<Required<FiltresUtilisateurs>>(FILTRES_VIDES);
  const [tri, setTri] = useState<ColonneTri>('nom');
  const [sensTri, setSensTri] = useState<SensTri>('asc');
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState<(typeof PAGE_SIZE_OPTIONS)[number]>(
    PAGE_SIZE_OPTIONS[1],
  );

  const chargementInitialFait = useRef(false);

  const isAdminGeneral = user?.role_ccfn === 'UTI-G';
  const isAdminFonctionnel = user?.role_ccfn === 'UTI-F';
  const canManageUsers = isAdminGeneral || isAdminFonctionnel;

  // §5.7.1 : UTI-G administre les UTI-F
  // §5.7.2 : UTI-F administre les UTI-S
  const roleGere = isAdminGeneral ? 'UTI-F' : 'UTI-S';
  const roleLabel = isAdminGeneral
    ? 'Administrateurs Fonctionnels'
    : 'Simples Utilisateurs';

  const chargerUtilisateurs = useCallback(
    async (criteres: Required<FiltresUtilisateurs>) => {
      try {
        setRefreshing(true);
        setError(null);
        setUtilisateurs(await fetchUtilisateurs(criteres));
        setFiltresAppliques(criteres);
        setPage(1);
      } catch (err) {
        console.error('Erreur lors du chargement des utilisateurs:', err);
        setError(
          extractApiErrorMessage(
            err,
            'Impossible de charger les utilisateurs. Vérifiez vos autorisations.',
          ),
        );
      } finally {
        setRefreshing(false);
      }
    },
    [],
  );

  useEffect(() => {
    if (chargementInitialFait.current) {
      return;
    }

    chargementInitialFait.current = true;

    void (async () => {
      try {
        setUser(await fetchMe());
      } catch (err) {
        console.error('Erreur lors du chargement du compte:', err);
        setError(
          extractApiErrorMessage(
            err,
            'Impossible de charger votre compte. Reconnectez-vous puis réessayez.',
          ),
        );
      }

      await chargerUtilisateurs(FILTRES_VIDES);
      setLoading(false);
    })();
  }, [chargerUtilisateurs]);

  const utilisateursTries = useMemo(() => {
    const copie = [...utilisateurs];
    copie.sort((a, b) => {
      const ordre = comparer(a, b, tri);
      return sensTri === 'asc' ? ordre : -ordre;
    });
    return copie;
  }, [utilisateurs, tri, sensTri]);

  const totalPages = Math.max(1, Math.ceil(utilisateursTries.length / pageSize));
  const currentPage = Math.min(page, totalPages);

  const utilisateursPage = useMemo(() => {
    const debut = (currentPage - 1) * pageSize;
    return utilisateursTries.slice(debut, debut + pageSize);
  }, [utilisateursTries, currentPage, pageSize]);

  const nbActifs = utilisateurs.filter((u) => u.actif).length;
  const filtreActif = Object.values(filtresAppliques).some(
    (valeur) => valeur !== '',
  );
  const rangeStart =
    utilisateursTries.length === 0 ? 0 : (currentPage - 1) * pageSize + 1;
  const rangeEnd = Math.min(currentPage * pageSize, utilisateursTries.length);

  function onChangeFiltre(
    champ: keyof FiltresUtilisateurs,
    valeur: string,
  ): void {
    setFiltres((precedents) => ({ ...precedents, [champ]: valeur }));
  }

  function onSubmitFiltres(event: React.FormEvent<HTMLFormElement>): void {
    event.preventDefault();
    void chargerUtilisateurs(filtres);
  }

  function onReinitialiser(): void {
    setFiltres(FILTRES_VIDES);
    void chargerUtilisateurs(FILTRES_VIDES);
  }

  // Un nouveau clic sur la colonne déjà triée inverse le sens ; changer de
  // colonne repart en ordre croissant.
  function onTrier(colonne: ColonneTri): void {
    if (colonne === tri) {
      setSensTri((sens) => (sens === 'asc' ? 'desc' : 'asc'));
      return;
    }

    setTri(colonne);
    setSensTri('asc');
  }

  function handleUtilisateurCreated(nouvelUtilisateur: Utilisateur) {
    setUtilisateurs((prev) => [nouvelUtilisateur, ...prev]);
    setCreateDialogOpen(false);
  }

  function handleUtilisateurUpdated(utilisateurMisAJour: Utilisateur) {
    setUtilisateurs((prev) =>
      prev.map((u) =>
        u.id === utilisateurMisAJour.id ? utilisateurMisAJour : u,
      ),
    );
  }

  if (!canManageUsers && !loading) {
    return (
      <div className="rounded-xl border bg-card p-8 shadow-sm">
        <div className="flex flex-col items-center gap-4 text-center">
          <div className="flex h-16 w-16 items-center justify-center rounded-full bg-destructive/10">
            <AlertCircle className="h-8 w-8 text-destructive" />
          </div>
          <div>
            <h2 className="text-lg font-semibold">Accès non autorisé</h2>
            <p className="mt-2 text-sm text-muted-foreground">
              La gestion des utilisateurs est réservée aux administrateurs (UTI-G
              et UTI-F).
            </p>
          </div>
        </div>
      </div>
    );
  }

  return (
    <>
      <div className="mb-8 flex flex-wrap items-center justify-between gap-4">
        <div className="flex items-center gap-3">
          <div className="flex h-12 w-12 items-center justify-center rounded-xl bg-primary/10">
            <UsersIcon className="h-6 w-6 text-primary" />
          </div>
          <div>
            <h1 className="text-2xl font-bold tracking-tight">
              Gestion des utilisateurs
            </h1>
            <p className="text-sm text-muted-foreground">
              Administration des {roleLabel}
            </p>
          </div>
        </div>

        {!loading && canManageUsers ? (
          <Button onClick={() => setCreateDialogOpen(true)}>
            <Plus className="h-4 w-4" />
            Créer un {roleGere}
          </Button>
        ) : null}
      </div>

      {error ? (
        <Alert variant="destructive" className="mb-6">
          <AlertCircle className="h-4 w-4" />
          <AlertTitle>Erreur</AlertTitle>
          <AlertDescription>{error}</AlertDescription>
        </Alert>
      ) : null}

      <Card className="mb-6">
        <CardContent className="grid divide-y p-0 sm:grid-cols-3 sm:divide-x sm:divide-y-0">
          <Indicateur
            icone={UsersIcon}
            libelle={`${roleGere} administrés`}
            valeur={utilisateurs.length}
          />
          <Indicateur
            icone={UserCheck}
            libelle="Comptes actifs"
            valeur={nbActifs}
            accent="succes"
          />
          <Indicateur
            icone={UserX}
            libelle="Comptes désactivés"
            valeur={utilisateurs.length - nbActifs}
            accent="alerte"
          />
        </CardContent>
      </Card>

      <Card className="mb-6">
        <CardHeader className="border-b pb-6">
          <CardTitle className="text-base">Rechercher un utilisateur</CardTitle>
          <CardDescription>
            Les filtres portent sur les comptes de votre périmètre
            d&apos;administration.
          </CardDescription>
        </CardHeader>

        <CardContent className="pt-6">
          <form className="space-y-4" onSubmit={onSubmitFiltres}>
            <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
              <div className="space-y-2">
                <Label htmlFor="filtre-email">Adresse e-mail</Label>
                <Input
                  id="filtre-email"
                  placeholder="jean.dupont@exemple.fr"
                  value={filtres.email}
                  onChange={(event) =>
                    onChangeFiltre('email', event.target.value)
                  }
                />
              </div>

              <div className="space-y-2">
                <Label htmlFor="filtre-recherche">
                  Nom, prénom ou téléphone
                </Label>
                <Input
                  id="filtre-recherche"
                  placeholder="Dupont, Jean ou 06 12 34 56 78"
                  value={filtres.recherche}
                  onChange={(event) =>
                    onChangeFiltre('recherche', event.target.value)
                  }
                />
              </div>

              <div className="space-y-2">
                <Label htmlFor="filtre-statut">Statut du compte</Label>
                <select
                  id="filtre-statut"
                  className={cn(selectClassName, 'w-full')}
                  value={filtres.statut}
                  onChange={(event) =>
                    onChangeFiltre('statut', event.target.value)
                  }
                >
                  <option value="">Tous les statuts</option>
                  <option value="actif">Actifs</option>
                  <option value="inactif">Désactivés</option>
                </select>
              </div>
            </div>

            <div className="flex flex-wrap items-center gap-2">
              <Button type="submit" disabled={refreshing}>
                {refreshing ? (
                  <Loader2 className="h-4 w-4 animate-spin" />
                ) : (
                  <Search className="h-4 w-4" />
                )}
                Filtrer
              </Button>
              <Button
                type="button"
                variant="outline"
                onClick={onReinitialiser}
                disabled={refreshing}
              >
                <RotateCcw className="h-4 w-4" />
                Réinitialiser
              </Button>
            </div>
          </form>
        </CardContent>
      </Card>

      <Card>
        <CardHeader className="gap-4 border-b pb-6">
          <div className="flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between">
            <div>
              <CardTitle className="text-base">{roleLabel}</CardTitle>
              <CardDescription>
                {utilisateurs.length} compte
                {utilisateurs.length > 1 ? 's' : ''}
                {filtreActif ? ' correspondant aux filtres' : ' au total'}
              </CardDescription>
            </div>

            <div>
              <Label htmlFor="utilisateurs-page-size" className="sr-only">
                Lignes par page
              </Label>
              <select
                id="utilisateurs-page-size"
                className={cn(selectClassName, 'min-w-[140px]')}
                value={pageSize}
                onChange={(event) => {
                  setPageSize(
                    Number(
                      event.target.value,
                    ) as (typeof PAGE_SIZE_OPTIONS)[number],
                  );
                  setPage(1);
                }}
              >
                {PAGE_SIZE_OPTIONS.map((size) => (
                  <option key={size} value={size}>
                    {size} par page
                  </option>
                ))}
              </select>
            </div>
          </div>
        </CardHeader>

        <CardContent className="p-0">
          {loading ? (
            <div className="space-y-3 p-6">
              <Skeleton className="h-12 w-full" />
              <Skeleton className="h-12 w-full" />
              <Skeleton className="h-12 w-full" />
            </div>
          ) : (
            <>
              <UtilisateursList
                utilisateurs={utilisateursPage}
                currentUser={user}
                onUtilisateurUpdated={handleUtilisateurUpdated}
                tri={tri}
                sensTri={sensTri}
                onTrier={onTrier}
                filtreActif={filtreActif}
              />

              {utilisateursTries.length > 0 ? (
                <div className="flex flex-col gap-3 border-t px-4 py-4 sm:flex-row sm:items-center sm:justify-between">
                  <p className="text-sm text-muted-foreground">
                    Affichage de {rangeStart} à {rangeEnd} sur{' '}
                    {utilisateursTries.length} utilisateur
                    {utilisateursTries.length > 1 ? 's' : ''}
                  </p>

                  <div className="flex items-center gap-2">
                    <Button
                      type="button"
                      variant="outline"
                      size="sm"
                      onClick={() => setPage((courante) => courante - 1)}
                      disabled={currentPage <= 1}
                    >
                      <ChevronLeft className="h-4 w-4" />
                      Précédent
                    </Button>
                    <span className="min-w-[4.5rem] text-center text-sm tabular-nums text-muted-foreground">
                      {currentPage} / {totalPages}
                    </span>
                    <Button
                      type="button"
                      variant="outline"
                      size="sm"
                      onClick={() => setPage((courante) => courante + 1)}
                      disabled={currentPage >= totalPages}
                    >
                      Suivant
                      <ChevronRight className="h-4 w-4" />
                    </Button>
                  </div>
                </div>
              ) : null}
            </>
          )}
        </CardContent>
      </Card>

      {canManageUsers ? (
        <CreateUtilisateurDialog
          open={createDialogOpen}
          onOpenChange={setCreateDialogOpen}
          roleGere={roleGere}
          onUtilisateurCreated={handleUtilisateurCreated}
        />
      ) : null}
    </>
  );
}
