import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Link, useSearchParams } from 'react-router-dom';
import { api } from '@/api/client';
import type { AdminProject, AdminUser } from '@/api/types';
import { useAuth, humanMessage } from '@/auth/AuthProvider';

/**
 * Administration hors projet.
 *
 * Volontairement séparée des écrans Membres et Intégration, qui répondent à
 * « qui a accès à CE projet ? ». Ici la question est autre : « qui existe dans
 * l'outil, et où va-t-il ? ». Elle traverse les projets, donc elle traverse
 * aussi les administrateurs de projet — d'où le rôle super-administrateur.
 *
 * Deux onglets, pas davantage. Un panneau d'administration qui grossit sans
 * discipline devient l'endroit où l'on range ce qu'on ne sait pas classer.
 */
export function AdminPage() {
    const { user } = useAuth();
    const [params, setParams] = useSearchParams();
    const tab = params.get('tab') === 'projects' ? 'projects' : 'users';

    if (user && !user.isSuperAdmin) {
        return <NotSuperAdmin />;
    }

    return (
        <div className="flex h-full flex-col bg-ink-100">
            <header className="shrink-0 border-b border-ink-200 bg-white px-4 py-2.5">
                <div className="flex items-center gap-1">
                    <Link to="/projects" className="mr-2 text-sm font-semibold text-ink-900 hover:text-accent">
                        TQ-Slator
                    </Link>

                    <div className="h-5 w-px bg-ink-200" />

                    <Link
                        to="/projects"
                        className="rounded px-2.5 py-1 text-sm text-ink-600 transition-colors hover:bg-ink-100"
                    >
                        Projets
                    </Link>
                    <span className="rounded bg-accent-soft px-2.5 py-1 text-sm font-medium text-accent">
                        Administration
                    </span>

                    <span className="ml-auto text-xs text-ink-400">{user?.name}</span>
                </div>
            </header>

            <div className="min-h-0 flex-1 overflow-y-auto">
                <div className="mx-auto max-w-5xl px-6 py-8">
                    <h1 className="text-xl font-semibold tracking-tight text-ink-900">Administration</h1>
                    <p className="mt-1 text-sm text-ink-500">
                        Comptes et projets de toute l'organisation.
                    </p>

                    <div className="mt-6 flex gap-1 border-b border-ink-200">
                        {(
                            [
                                ['users', 'Utilisateurs'],
                                ['projects', 'Projets'],
                            ] as const
                        ).map(([value, label]) => (
                            <button
                                key={value}
                                onClick={() => setParams({ tab: value }, { replace: true })}
                                className={`-mb-px border-b-2 px-3 py-2 text-sm transition-colors ${
                                    tab === value
                                        ? 'border-accent font-medium text-accent'
                                        : 'border-transparent text-ink-500 hover:text-ink-800'
                                }`}
                            >
                                {label}
                            </button>
                        ))}
                    </div>

                    {tab === 'users' ? <UsersTab /> : <ProjectsTab />}
                </div>
            </div>
        </div>
    );
}

function NotSuperAdmin() {
    return (
        <div className="flex h-full items-center justify-center px-6">
            <div className="max-w-md text-center">
                <p className="text-lg font-medium text-ink-800">Réservé aux super-administrateurs</p>
                <p className="mt-2 text-sm text-ink-500">
                    Cette page donne accès aux comptes de toute l'organisation. Pour gérer les accès
                    d'un projet dont vous êtes administrateur, ouvrez ce projet et allez dans
                    « Membres ».
                </p>
                <Link
                    to="/projects"
                    className="mt-6 inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700"
                >
                    Revenir aux projets
                </Link>
            </div>
        </div>
    );
}

// ── Utilisateurs ─────────────────────────────────────────────────────────

function UsersTab() {
    const [search, setSearch] = useState('');
    const data = useQuery({
        queryKey: ['admin-users', search],
        queryFn: () => api.adminUsers(search || undefined),
    });

    const users = data.data?.users ?? [];
    const orphans = users.filter((u) => u.memberships.length === 0).length;

    return (
        <div className="mt-6">
            <div className="flex items-center gap-3">
                <input
                    type="search"
                    value={search}
                    onChange={(e) => setSearch(e.target.value)}
                    placeholder="Rechercher un nom ou une adresse…"
                    className="min-w-64 flex-1 rounded-md border border-ink-300 px-3 py-2 text-sm outline-none focus:border-accent"
                />
                <span className="shrink-0 text-xs text-ink-400">
                    {users.length} compte{users.length > 1 ? 's' : ''}
                </span>
            </div>

            {/* Un compte sans projet ne voit rien du tout. C'est soit une
                invitation oubliée, soit un départ mal soldé — dans les deux cas
                quelque chose à traiter, pas une curiosité. */}
            {orphans > 0 && (
                <p className="mt-3 rounded-md bg-amber-50 px-3 py-2 text-xs text-amber-900">
                    {orphans} compte{orphans > 1 ? 's' : ''} sans aucun projet : ces personnes se
                    connectent mais ne voient rien.
                </p>
            )}

            <div className="mt-4 divide-y divide-ink-100 overflow-hidden rounded-lg border border-ink-200 bg-white">
                {users.map((user) => (
                    <UserRow
                        key={user.uuid}
                        user={user}
                        superAdminCount={data.data?.superAdminCount ?? 0}
                    />
                ))}

                {data.isSuccess && users.length === 0 && (
                    <p className="px-4 py-6 text-center text-sm text-ink-400">Aucun compte trouvé.</p>
                )}
            </div>
        </div>
    );
}

function UserRow({ user, superAdminCount }: { user: AdminUser; superAdminCount: number }) {
    const { user: current } = useAuth();
    const queryClient = useQueryClient();
    const [error, setError] = useState<string | null>(null);

    const isSelf = current?.email === user.email;
    const isLastSuperAdmin = user.isSuperAdmin && superAdminCount <= 1;

    const update = useMutation({
        mutationFn: (body: { isActive?: boolean; isSuperAdmin?: boolean }) =>
            api.updateAdminUser(user.uuid, body),
        onSuccess: () => {
            setError(null);
            void queryClient.invalidateQueries({ queryKey: ['admin-users'] });
        },
        onError: (caught) => setError(humanMessage(caught)),
    });

    return (
        <div className={`px-4 py-3 ${user.isActive ? '' : 'bg-ink-50'}`}>
            <div className="flex flex-wrap items-center gap-x-3 gap-y-1">
                <span className={`text-sm ${user.isActive ? 'text-ink-800' : 'text-ink-400 line-through'}`}>
                    {user.name}
                </span>
                <span className="text-xs text-ink-400">{user.email}</span>

                {user.isSuperAdmin && (
                    <span className="rounded bg-accent-soft px-1.5 py-0.5 text-[11px] font-medium text-accent">
                        super-admin
                    </span>
                )}
                {user.isExternal && (
                    <span className="rounded bg-amber-100 px-1.5 py-0.5 text-[11px] text-amber-900">
                        externe
                    </span>
                )}
                {!user.isActive && (
                    <span className="rounded bg-ink-200 px-1.5 py-0.5 text-[11px] text-ink-600">
                        désactivé
                    </span>
                )}

                <span className="ml-auto flex shrink-0 items-center gap-2">
                    <button
                        onClick={() => update.mutate({ isSuperAdmin: !user.isSuperAdmin })}
                        disabled={update.isPending || isSelf || isLastSuperAdmin}
                        title={
                            isSelf
                                ? 'On ne modifie pas son propre rôle depuis cet écran.'
                                : isLastSuperAdmin
                                  ? 'Il doit rester au moins un super-administrateur.'
                                  : undefined
                        }
                        className="rounded border border-ink-300 px-2 py-1 text-xs text-ink-600 transition-colors hover:bg-ink-100 disabled:cursor-not-allowed disabled:opacity-40"
                    >
                        {user.isSuperAdmin ? 'Retirer super-admin' : 'Nommer super-admin'}
                    </button>

                    <button
                        onClick={() => update.mutate({ isActive: !user.isActive })}
                        disabled={update.isPending || isSelf || (!user.isActive ? false : isLastSuperAdmin)}
                        title={isSelf ? 'On ne désactive pas son propre compte.' : undefined}
                        className={`rounded px-2 py-1 text-xs transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${
                            user.isActive
                                ? 'border border-red-200 text-red-700 hover:bg-red-50'
                                : 'border border-ink-300 text-ink-600 hover:bg-ink-100'
                        }`}
                    >
                        {user.isActive ? 'Désactiver' : 'Réactiver'}
                    </button>
                </span>
            </div>

            <div className="mt-1.5 flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-ink-400">
                {user.memberships.length === 0 ? (
                    <span className="text-amber-700">aucun projet</span>
                ) : (
                    user.memberships.map((m) => (
                        <span key={m.projectUuid}>
                            <Link
                                to={`/p/${m.projectUuid}/members`}
                                className="text-ink-600 hover:text-accent"
                            >
                                {m.project}
                            </Link>
                            <span className="text-ink-300"> · </span>
                            {m.role}
                            <span className="text-ink-300"> · </span>
                            <span className="font-mono">
                                {m.coversAllLocales ? 'toutes langues' : m.locales.join(', ')}
                            </span>
                        </span>
                    ))
                )}

                <span className="ml-auto">
                    {user.lastLoginAt
                        ? `dernière connexion le ${new Date(user.lastLoginAt).toLocaleDateString('fr-FR')}`
                        : 'jamais connecté'}
                </span>
            </div>

            {error && <p className="mt-2 text-xs text-red-600">{error}</p>}
        </div>
    );
}

// ── Projets ──────────────────────────────────────────────────────────────

function ProjectsTab() {
    const data = useQuery({ queryKey: ['admin-projects'], queryFn: () => api.adminProjects() });
    const queryClient = useQueryClient();

    return (
        <div className="mt-6">
            <CreateProjectForm
                locales={data.data?.locales ?? []}
                onDone={() => void queryClient.invalidateQueries({ queryKey: ['admin-projects'] })}
            />

            <div className="mt-8 divide-y divide-ink-100 overflow-hidden rounded-lg border border-ink-200 bg-white">
                {data.data?.projects.map((project) => (
                    <ProjectRow key={project.uuid} project={project} />
                ))}
            </div>
        </div>
    );
}

function ProjectRow({ project }: { project: AdminProject }) {
    return (
        <div className="px-4 py-3">
            <div className="flex flex-wrap items-center gap-x-3 gap-y-1">
                <Link
                    to={`/p/${project.uuid}/editor`}
                    className="text-sm font-medium text-ink-800 hover:text-accent"
                >
                    {project.name}
                </Link>
                <span className="font-mono text-[11px] text-ink-400">{project.slug}</span>

                {/* Un projet sans propriétaire n'est administrable par personne :
                    plus d'invitation possible, plus de publication. C'est la
                    seule anomalie que cet écran doit crier. */}
                {project.owners.length === 0 && (
                    <span className="rounded bg-red-100 px-1.5 py-0.5 text-[11px] font-medium text-red-800">
                        aucun propriétaire
                    </span>
                )}

                {/* Sans plateforme, aucune clé ne peut être rattachée et aucun
                    bundle ne peut être construit : le projet existe mais ne
                    livre rien. Un projet fraîchement créé est dans cet état. */}
                {project.platformCount === 0 && (
                    <span className="rounded bg-amber-100 px-1.5 py-0.5 text-[11px] font-medium text-amber-900">
                        aucune plateforme
                    </span>
                )}

                <span className="ml-auto flex shrink-0 gap-2 text-xs">
                    <Link
                        to={`/p/${project.uuid}/members`}
                        className="rounded border border-ink-300 px-2 py-1 text-ink-600 hover:bg-ink-100"
                    >
                        Membres
                    </Link>
                    <Link
                        to={`/p/${project.uuid}/integration`}
                        className="rounded border border-ink-300 px-2 py-1 text-ink-600 hover:bg-ink-100"
                    >
                        Intégration
                    </Link>
                </span>
            </div>

            <div className="mt-1.5 flex flex-wrap gap-x-3 text-[11px] text-ink-400">
                <span className="font-mono">
                    {project.sourceLocale} → {project.targetLocales.join(', ') || 'aucune cible'}
                </span>
                <span>{project.platformCount} plateformes</span>
                <span>{project.environmentCount} environnements</span>
                <span>{project.memberCount} membres</span>
                {project.owners.length > 0 && <span>propriétaire : {project.owners.join(', ')}</span>}
            </div>
        </div>
    );
}

function CreateProjectForm({
    locales,
    onDone,
}: {
    locales: { code: string; name: string; nativeName: string }[];
    onDone: () => void;
}) {
    const [open, setOpen] = useState(false);
    const [name, setName] = useState('');
    const [slug, setSlug] = useState('');
    const [description, setDescription] = useState('');
    const [sourceLocale, setSourceLocale] = useState('fr-FR');
    const [targets, setTargets] = useState<string[]>([]);
    const [error, setError] = useState<string | null>(null);
    const [message, setMessage] = useState<string | null>(null);

    const create = useMutation({
        mutationFn: () =>
            api.createProject({ name, slug, description, sourceLocale, targetLocales: targets }),
        onSuccess: (project) => {
            setMessage(
                `Projet « ${project.name} » créé, avec ses trois environnements. Vous en êtes propriétaire.`,
            );
            setError(null);
            setName('');
            setSlug('');
            setDescription('');
            setTargets([]);
            // On referme : un formulaire vidé sur place ressemble à un échec
            // silencieux. Refermer fait apparaître la confirmation, et la
            // nouvelle ligne juste en dessous.
            setOpen(false);
            onDone();
        },
        onError: (caught) => {
            setError(humanMessage(caught));
            setMessage(null);
        },
    });

    if (!open) {
        return (
            <div>
                <button
                    onClick={() => setOpen(true)}
                    className="rounded-md bg-accent px-3 py-2 text-sm font-medium text-white transition-colors hover:bg-indigo-700"
                >
                    Nouveau projet
                </button>
                {message && <p className="mt-3 text-xs text-emerald-700">{message}</p>}
            </div>
        );
    }

    return (
        <form
            onSubmit={(e) => {
                e.preventDefault();
                create.mutate();
            }}
            className="rounded-lg border border-ink-200 bg-white p-5 shadow-sm"
        >
            <h2 className="mb-4 text-sm font-medium text-ink-800">Nouveau projet</h2>

            <div className="flex flex-wrap gap-3">
                <input
                    required
                    value={name}
                    onChange={(e) => {
                        setName(e.target.value);
                        // Le slug se déduit du nom tant qu'on n'y a pas touché.
                        // Il finit dans des URL de livraison et dans les dépôts
                        // clients : le laisser vide serait un piège.
                        setSlug(
                            e.target.value
                                .toLowerCase()
                                .normalize('NFD')
                                .replace(/[\u0300-\u036f]/g, '')
                                .replace(/[^a-z0-9]+/g, '-')
                                .replace(/^-|-$/g, ''),
                        );
                    }}
                    placeholder="Nom du projet"
                    className="min-w-56 flex-1 rounded-md border border-ink-300 px-3 py-2 text-sm outline-none focus:border-accent"
                />

                <input
                    required
                    value={slug}
                    onChange={(e) => setSlug(e.target.value)}
                    placeholder="slug-du-projet"
                    className="min-w-44 rounded-md border border-ink-300 px-3 py-2 font-mono text-sm outline-none focus:border-accent"
                />

                <select
                    value={sourceLocale}
                    onChange={(e) => setSourceLocale(e.target.value)}
                    className="rounded-md border border-ink-300 bg-white px-3 py-2 text-sm outline-none focus:border-accent"
                >
                    {locales.map((l) => (
                        <option key={l.code} value={l.code}>
                            Source : {l.nativeName}
                        </option>
                    ))}
                </select>
            </div>

            <input
                value={description}
                onChange={(e) => setDescription(e.target.value)}
                placeholder="Description (facultative)"
                className="mt-3 w-full rounded-md border border-ink-300 px-3 py-2 text-sm outline-none focus:border-accent"
            />

            <p className="mb-2 mt-4 text-[11px] font-semibold uppercase tracking-wide text-ink-400">
                Langues cibles
            </p>
            <div className="flex flex-wrap gap-1.5">
                {locales
                    .filter((l) => l.code !== sourceLocale)
                    .map((l) => {
                        const on = targets.includes(l.code);

                        return (
                            <button
                                key={l.code}
                                type="button"
                                onClick={() =>
                                    setTargets((prev) =>
                                        on ? prev.filter((c) => c !== l.code) : [...prev, l.code],
                                    )
                                }
                                className={`rounded px-2 py-1 text-xs transition-colors ${
                                    on ? 'bg-accent text-white' : 'bg-ink-100 text-ink-600 hover:bg-ink-200'
                                }`}
                            >
                                {l.nativeName}
                            </button>
                        );
                    })}
            </div>
            <p className="mt-2 text-[11px] text-ink-400">
                La langue source ne se change plus après la création : la modifier invaliderait
                l'empreinte de chaque traduction et basculerait tout le contenu en « à revoir ».
            </p>

            {/* Hauteur bornée : une erreur serveur inattendue peut faire
                plusieurs milliers de caractères, et pousserait sinon le bouton
                de validation hors de l'écran. */}
            {error && (
                <p className="mt-3 max-h-24 overflow-y-auto rounded bg-red-50 px-3 py-2 text-xs text-red-700">
                    {error}
                </p>
            )}

            <div className="mt-4 flex items-center gap-3">
                <button
                    type="submit"
                    disabled={create.isPending}
                    className="rounded-md bg-accent px-3 py-2 text-sm font-medium text-white transition-colors hover:bg-indigo-700 disabled:bg-ink-300"
                >
                    {create.isPending ? 'Création…' : 'Créer le projet'}
                </button>
                <button
                    type="button"
                    onClick={() => setOpen(false)}
                    className="text-sm text-ink-500 hover:text-ink-800"
                >
                    Annuler
                </button>
            </div>
        </form>
    );
}
