import { Form, Head, Link, router } from '@inertiajs/react';
import { ShieldOff, ShieldX, UserCheck } from 'lucide-react';
import { useMemo, useState } from 'react';
import UserController from '@/actions/App/Http/Controllers/Admin/UserController';
import { ConfirmDialog } from '@/components/confirm-dialog';
import Heading from '@/components/heading';
import InputError from '@/components/input-error';
import PasswordInput from '@/components/password-input';
import { SearchableSelect } from '@/components/searchable-select';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Separator } from '@/components/ui/separator';
import { formatDate } from '@/lib/utils';
import { index } from '@/routes/admin/users';
import { dashboard } from '@/routes';

type LoginHistoryEntry = {
    id: number;
    event: string;
    description: string;
    ip_address: string | null;
    created_at: string | null;
};

const LOGIN_EVENT_VARIANTS: Record<
    string,
    'default' | 'secondary' | 'destructive'
> = {
    'login.success': 'secondary',
    logout: 'secondary',
    'user.locked_out': 'destructive',
};

type RoleOption = {
    name: string;
    label: string;
};

type DepartmentOption = {
    id: number;
    code: string;
    name: string;
};

type EditableUser = {
    id: number;
    name: string;
    email: string;
    roles: string[];
    department_id: number | null;
    is_active: boolean;
    deactivated_at: string | null;
    deactivated_by: string | null;
    two_factor_enabled: boolean;
};

export default function UsersEdit({
    user,
    roles,
    departments,
    loginHistory,
    can,
}: {
    user: EditableUser;
    roles: RoleOption[];
    departments: DepartmentOption[];
    loginHistory: LoginHistoryEntry[];
    can: {
        deactivate: boolean;
        resetPassword: boolean;
        revokeTwoFactor: boolean;
        viewLoginHistory: boolean;
    };
}) {
    const [selectedRoles, setSelectedRoles] = useState<string[]>(user.roles);
    const [departmentId, setDepartmentId] = useState(
        user.department_id ? String(user.department_id) : 'none',
    );

    const departmentOptions = useMemo(
        () =>
            departments.map((department) => ({
                value: String(department.id),
                label: `${department.code} — ${department.name}`,
            })),
        [departments],
    );

    const showStatusCard =
        can.deactivate ||
        can.resetPassword ||
        can.revokeTwoFactor ||
        can.viewLoginHistory;

    function toggleRole(role: string, checked: boolean) {
        setSelectedRoles((current) =>
            checked
                ? [...current, role]
                : current.filter((value) => value !== role),
        );
    }

    return (
        <>
            <Head title={`Modifier ${user.name}`} />

            <div className="flex h-full flex-1 flex-col gap-6 p-4 md:p-6">
                <Heading
                    title="Modifier l’utilisateur"
                    description={user.email}
                />

                <div
                    className={
                        showStatusCard
                            ? 'grid gap-6 lg:grid-cols-[minmax(0,1fr)_20rem] xl:grid-cols-[minmax(0,1fr)_22rem]'
                            : 'max-w-2xl'
                    }
                >
                    <Card>
                        <CardHeader>
                            <CardTitle className="text-base">
                                Informations du compte
                            </CardTitle>
                            <CardDescription>
                                Identifiants, département et rôles
                            </CardDescription>
                        </CardHeader>
                        <CardContent>
                            <Form
                                {...UserController.update.form(user.id)}
                                className="space-y-6"
                            >
                                {({ processing, errors }) => (
                                    <>
                                        <div className="grid gap-4 sm:grid-cols-2">
                                            <div className="grid gap-2">
                                                <Label htmlFor="name">
                                                    Nom
                                                </Label>
                                                <Input
                                                    id="name"
                                                    name="name"
                                                    defaultValue={user.name}
                                                    required
                                                />
                                                <InputError
                                                    message={errors.name}
                                                />
                                            </div>

                                            <div className="grid gap-2">
                                                <Label htmlFor="email">
                                                    E-mail
                                                </Label>
                                                <Input
                                                    id="email"
                                                    name="email"
                                                    type="email"
                                                    defaultValue={user.email}
                                                    required
                                                />
                                                <InputError
                                                    message={errors.email}
                                                />
                                            </div>
                                        </div>

                                        <div className="grid gap-4 sm:grid-cols-2">
                                            <div className="grid gap-2">
                                                <Label htmlFor="password">
                                                    Nouveau mot de passe
                                                </Label>
                                                <PasswordInput
                                                    id="password"
                                                    name="password"
                                                    placeholder="Laisser vide pour ne pas changer"
                                                />
                                                <InputError
                                                    message={errors.password}
                                                />
                                            </div>

                                            <div className="grid gap-2">
                                                <Label htmlFor="password_confirmation">
                                                    Confirmation du mot de
                                                    passe
                                                </Label>
                                                <PasswordInput
                                                    id="password_confirmation"
                                                    name="password_confirmation"
                                                />
                                            </div>
                                        </div>

                                        <div className="grid gap-2">
                                            <Label>Département</Label>
                                            <SearchableSelect
                                                options={departmentOptions}
                                                value={departmentId}
                                                onChange={setDepartmentId}
                                                placeholder="Choisir un département…"
                                                noneLabel="Aucun"
                                                noneValue="none"
                                            />
                                            <input
                                                type="hidden"
                                                name="department_id"
                                                value={
                                                    departmentId === 'none'
                                                        ? ''
                                                        : departmentId
                                                }
                                            />
                                            <p className="text-muted-foreground text-xs">
                                                Appliqué à la fiche
                                                collaborateur associée.
                                            </p>
                                            <InputError
                                                message={errors.department_id}
                                            />
                                        </div>

                                        <div className="grid gap-3">
                                            <Label>Rôles</Label>
                                            {roles.map((role) => (
                                                <label
                                                    key={role.name}
                                                    className="flex items-center gap-2 text-sm"
                                                >
                                                    <Checkbox
                                                        checked={selectedRoles.includes(
                                                            role.name,
                                                        )}
                                                        onCheckedChange={(
                                                            checked,
                                                        ) =>
                                                            toggleRole(
                                                                role.name,
                                                                checked ===
                                                                    true,
                                                            )
                                                        }
                                                    />
                                                    <span>{role.label}</span>
                                                    {selectedRoles.includes(
                                                        role.name,
                                                    ) && (
                                                        <input
                                                            type="hidden"
                                                            name="roles[]"
                                                            value={role.name}
                                                        />
                                                    )}
                                                </label>
                                            ))}
                                            <InputError
                                                message={errors.roles}
                                            />
                                        </div>

                                        <div className="flex gap-3">
                                            <Button disabled={processing}>
                                                Enregistrer
                                            </Button>
                                            <Button variant="outline" asChild>
                                                <Link href={index()}>
                                                    Annuler
                                                </Link>
                                            </Button>
                                        </div>
                                    </>
                                )}
                            </Form>
                        </CardContent>
                    </Card>

                    {showStatusCard && (
                        <Card className="h-fit lg:sticky lg:top-6">
                            <CardHeader>
                                <CardTitle className="flex items-center justify-between gap-3 text-base">
                                    Statut du compte
                                    <Badge
                                        variant={
                                            user.is_active
                                                ? 'secondary'
                                                : 'destructive'
                                        }
                                    >
                                        {user.is_active
                                            ? 'Actif'
                                            : 'Désactivé'}
                                    </Badge>
                                </CardTitle>
                                <CardDescription>
                                    Activation du compte et réinitialisation du
                                    mot de passe
                                </CardDescription>
                            </CardHeader>
                            <CardContent className="space-y-4">
                                {!user.is_active && user.deactivated_at && (
                                    <p className="text-sm text-muted-foreground">
                                        Désactivé le{' '}
                                        {formatDate(user.deactivated_at)}
                                        {user.deactivated_by &&
                                            ` par ${user.deactivated_by}`}
                                        .
                                    </p>
                                )}

                                <div className="flex flex-col gap-3">
                                    {can.deactivate &&
                                        (user.is_active ? (
                                            <ConfirmDialog
                                                trigger={
                                                    <Button
                                                        type="button"
                                                        variant="outline"
                                                        className="w-full justify-start"
                                                    >
                                                        <ShieldOff />
                                                        Désactiver le compte
                                                    </Button>
                                                }
                                                title={`Désactiver le compte de ${user.name} ?`}
                                                description="Cette personne ne pourra plus se connecter tant que le compte n'est pas réactivé."
                                                confirmLabel="Désactiver"
                                                onConfirm={() =>
                                                    router.post(
                                                        UserController.deactivate.url(
                                                            user.id,
                                                        ),
                                                        {},
                                                        {
                                                            preserveScroll: true,
                                                        },
                                                    )
                                                }
                                            />
                                        ) : (
                                            <Button
                                                type="button"
                                                variant="outline"
                                                className="w-full justify-start"
                                                onClick={() =>
                                                    router.post(
                                                        UserController.reactivate.url(
                                                            user.id,
                                                        ),
                                                        {},
                                                        {
                                                            preserveScroll: true,
                                                        },
                                                    )
                                                }
                                            >
                                                <UserCheck />
                                                Réactiver le compte
                                            </Button>
                                        ))}

                                    {can.resetPassword && (
                                        <ConfirmDialog
                                            trigger={
                                                <Button
                                                    type="button"
                                                    variant="outline"
                                                    className="w-full justify-start"
                                                >
                                                    Envoyer un lien de
                                                    réinitialisation
                                                </Button>
                                            }
                                            title="Envoyer un lien de réinitialisation ?"
                                            description={`Un e-mail sera envoyé à ${user.email} pour définir un nouveau mot de passe.`}
                                            confirmLabel="Envoyer"
                                            variant="default"
                                            onConfirm={() =>
                                                router.post(
                                                    UserController.sendPasswordResetLink.url(
                                                        user.id,
                                                    ),
                                                    {},
                                                    {
                                                        preserveScroll: true,
                                                    },
                                                )
                                            }
                                        />
                                    )}

                                    {can.revokeTwoFactor &&
                                        user.two_factor_enabled && (
                                            <ConfirmDialog
                                                trigger={
                                                    <Button
                                                        type="button"
                                                        variant="outline"
                                                        className="w-full justify-start"
                                                    >
                                                        <ShieldX />
                                                        Révoquer la 2FA
                                                    </Button>
                                                }
                                                title={`Révoquer la 2FA de ${user.name} ?`}
                                                description="Cette personne devra reconfigurer la double authentification lors de sa prochaine connexion."
                                                confirmLabel="Révoquer"
                                                variant="destructive"
                                                onConfirm={() =>
                                                    router.post(
                                                        UserController.revokeTwoFactor.url(
                                                            user.id,
                                                        ),
                                                        {},
                                                        {
                                                            preserveScroll: true,
                                                        },
                                                    )
                                                }
                                            />
                                        )}
                                </div>

                                {can.viewLoginHistory && (
                                    <>
                                        <Separator />

                                        <div className="space-y-3">
                                            <p className="text-sm font-medium">
                                                Historique de connexion
                                            </p>

                                            {loginHistory.length === 0 ? (
                                                <p className="text-sm text-muted-foreground">
                                                    Aucune activité récente.
                                                </p>
                                            ) : (
                                                <ul className="space-y-2">
                                                    {loginHistory.map(
                                                        (entry) => (
                                                            <li
                                                                key={entry.id}
                                                                className="flex flex-col gap-1 text-sm"
                                                            >
                                                                <div className="flex items-center justify-between gap-2">
                                                                    <Badge
                                                                        variant={
                                                                            LOGIN_EVENT_VARIANTS[
                                                                                entry
                                                                                    .event
                                                                            ] ??
                                                                            'outline'
                                                                        }
                                                                    >
                                                                        {
                                                                            entry.event
                                                                        }
                                                                    </Badge>
                                                                    <span className="text-xs whitespace-nowrap text-muted-foreground">
                                                                        {formatDate(
                                                                            entry.created_at,
                                                                        )}
                                                                    </span>
                                                                </div>
                                                                {entry.ip_address && (
                                                                    <span className="font-mono text-xs text-muted-foreground">
                                                                        {
                                                                            entry.ip_address
                                                                        }
                                                                    </span>
                                                                )}
                                                            </li>
                                                        ),
                                                    )}
                                                </ul>
                                            )}
                                        </div>
                                    </>
                                )}
                            </CardContent>
                        </Card>
                    )}
                </div>
            </div>
        </>
    );
}

UsersEdit.layout = {
    breadcrumbs: [
        { title: 'Tableau de bord', href: dashboard() },
        { title: 'Utilisateurs', href: index() },
        { title: 'Modifier', href: '#' },
    ],
};
