import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { api } from '@/api/client';
import { humanMessage, useAuth } from '@/auth/AuthProvider';

const MIN_PASSWORD_LENGTH = 12;

/**
 * Acceptation d'une invitation — la première page qu'un traducteur voit.
 *
 * Elle annonce à quoi il est invité AVANT de lui demander quoi que ce soit :
 * quel projet, quel rôle, quelles langues. Demander un mot de passe sans dire
 * pour quoi est la façon la plus sûre de faire abandonner quelqu'un, ou pire, de
 * lui faire croire à une tentative d'hameçonnage.
 */
export function InvitationPage() {
    const { token = '' } = useParams();
    const navigate = useNavigate();
    const { login } = useAuth();

    const [name, setName] = useState('');
    const [password, setPassword] = useState('');
    const [error, setError] = useState<string | null>(null);
    const [pending, setPending] = useState(false);

    const invitation = useQuery({
        queryKey: ['invitation', token],
        queryFn: () => api.invitationPreview(token),
        retry: false,
    });

    async function submit(event: React.FormEvent) {
        event.preventDefault();
        setError(null);
        setPending(true);

        try {
            await api.acceptInvitation(token, { name, password });

            // Connexion immédiate : demander de ressaisir des identifiants qu'on
            // vient de définir est une étape gratuite, juste après l'effort.
            await login(invitation.data?.email ?? '', password);
            navigate('/projects', { replace: true });
        } catch (caught) {
            setError(humanMessage(caught));
        } finally {
            setPending(false);
        }
    }

    if (invitation.isLoading) {
        return <Centered>Vérification de l'invitation…</Centered>;
    }

    if (invitation.isError) {
        return (
            <Centered>
                <div className="max-w-md text-center">
                    <p className="text-lg font-medium text-ink-800">Invitation non valable</p>
                    <p className="mt-2 text-sm text-ink-500">{humanMessage(invitation.error)}</p>
                    <Link
                        to="/login"
                        className="mt-6 inline-block text-sm text-accent underline-offset-4 hover:underline"
                    >
                        Aller à la page de connexion
                    </Link>
                </div>
            </Centered>
        );
    }

    const data = invitation.data;
    const tooShort = password.length > 0 && password.length < MIN_PASSWORD_LENGTH;

    return (
        <Centered>
            <div className="w-full max-w-md">
                <h1 className="text-2xl font-semibold tracking-tight text-ink-900">
                    Rejoindre {data?.project}
                </h1>
                <p className="mt-1 text-sm text-ink-500">
                    Invitation pour <span className="font-medium text-ink-700">{data?.email}</span>
                </p>

                <div className="mt-6 rounded-lg border border-ink-200 bg-white p-6 shadow-sm">
                    {/* Ce que l'invitation donne, énoncé avant toute saisie. */}
                    <dl className="mb-6 space-y-2 text-sm">
                        <div className="flex justify-between gap-4">
                            <dt className="text-ink-500">Rôle</dt>
                            <dd className="font-medium text-ink-800">{data?.role}</dd>
                        </div>
                        <div className="flex justify-between gap-4">
                            <dt className="text-ink-500">Langues</dt>
                            <dd className="text-right font-medium text-ink-800">
                                {data?.locales.length === 0
                                    ? 'toutes les langues du projet'
                                    : data?.locales.join(', ')}
                            </dd>
                        </div>
                    </dl>

                    <form onSubmit={submit}>
                        <label className="block">
                            <span className="text-sm font-medium text-ink-700">Votre nom</span>
                            <input
                                value={name}
                                onChange={(e) => setName(e.target.value)}
                                required
                                autoFocus
                                autoComplete="name"
                                className="mt-1.5 w-full rounded-md border border-ink-300 px-3 py-2 text-sm outline-none focus:border-accent"
                            />
                            <span className="mt-1 block text-xs text-ink-400">
                                Il apparaîtra sur les traductions que vous écrivez.
                            </span>
                        </label>

                        <label className="mt-4 block">
                            <span className="text-sm font-medium text-ink-700">Mot de passe</span>
                            <input
                                type="password"
                                value={password}
                                onChange={(e) => setPassword(e.target.value)}
                                required
                                minLength={MIN_PASSWORD_LENGTH}
                                autoComplete="new-password"
                                className={`mt-1.5 w-full rounded-md border px-3 py-2 text-sm outline-none focus:border-accent ${
                                    tooShort ? 'border-amber-400' : 'border-ink-300'
                                }`}
                            />
                            {/* Une longueur plutôt qu'une exigence de composition :
                                les règles « majuscule + chiffre + symbole » produisent
                                des mots de passe courts, difficiles à retenir et faciles
                                à casser. */}
                            <span
                                className={`mt-1 block text-xs ${tooShort ? 'text-amber-700' : 'text-ink-400'}`}
                            >
                                {MIN_PASSWORD_LENGTH} caractères minimum. Une phrase entière fait un
                                excellent mot de passe.
                            </span>
                        </label>

                        {data?.isExternal && (
                            <p className="mt-4 rounded-md bg-ink-50 px-3 py-2 text-xs text-ink-600">
                                Vous rejoignez ce projet comme prestataire externe. Votre accès est
                                limité aux langues ci-dessus et vos connexions sont journalisées.
                            </p>
                        )}

                        {error !== null && (
                            <p
                                role="alert"
                                className="mt-4 rounded-md bg-red-50 px-3 py-2 text-sm text-red-700"
                            >
                                {error}
                            </p>
                        )}

                        <button
                            type="submit"
                            disabled={pending || tooShort}
                            className="mt-6 w-full rounded-md bg-accent px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-indigo-700 disabled:opacity-60"
                        >
                            {pending ? 'Création du compte…' : 'Créer mon compte'}
                        </button>
                    </form>
                </div>

                <p className="mt-6 text-center text-xs text-ink-400">
                    Ce lien ne fonctionne qu'une fois. Si vous n'attendiez pas cette invitation,
                    fermez simplement cette page : aucun compte ne sera créé.
                </p>
            </div>
        </Centered>
    );
}

function Centered({ children }: { children: React.ReactNode }) {
    return <div className="flex h-full items-center justify-center px-6">{children}</div>;
}
