import { Eye, EyeOff, Plus, Trash2 } from 'lucide-react';
import type { FormEvent } from 'react';
import { useMemo, useState } from 'react';
import { toast } from 'sonner';

import { ConfigError, Field, InfoHint } from '@/components/admin/admin-form-parts';
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 {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Spinner } from '@/components/ui/spinner';
import {
    emptyUserForm,
    formatDate,
    isUserActive,
    roleLabel,
    userToForm,
} from '@/lib/admin';
import {
    createAdminUser,
    deleteAdminUser,
    updateAdminUser,
} from '@/lib/rag-client';
import type {
    AdminRole,
    AdminUser,
    UserFilterForm,
    UserForm,
} from '@/types/admin';

export function AdminUserCreateCard({
    onCreated,
}: {
    onCreated?: (user: AdminUser) => void;
}) {
    const [formData, setFormData] = useState<UserForm>(emptyUserForm);
    const [isSubmitting, setIsSubmitting] = useState(false);
    const [error, setError] = useState<string | undefined>();

    function setField<K extends keyof UserForm>(
        key: K,
        value: UserForm[K],
    ): void {
        setFormData((prev) => ({ ...prev, [key]: value }));
    }

    async function handleSubmit(
        event: FormEvent<HTMLFormElement>,
    ): Promise<void> {
        event.preventDefault();
        setIsSubmitting(true);
        setError(undefined);

        try {
            const payload = buildCreatePayload(formData);
            const created = await createAdminUser(payload);
            setFormData(emptyUserForm);
            onCreated?.(created);
        } catch (e) {
            setError(
                e instanceof Error ? e.message : 'Gagal membuat user.',
            );
        } finally {
            setIsSubmitting(false);
        }
    }

    return (
        <Card className="border-(--lecturer-border) bg-(--lecturer-surface)">
            <CardHeader>
                <CardTitle className="flex items-center gap-2">
                    <Plus className="size-5 text-(--lecturer-primary)" />
                    Tambah User
                </CardTitle>
                <CardDescription>
                    Payload mengikuti schema UpsertUser dari API.
                </CardDescription>
            </CardHeader>
            <CardContent>
                <UserFormFields
                    data={formData}
                    error={error}
                    isSubmitting={isSubmitting}
                    setField={setField}
                    submitLabel="Buat User"
                    onSubmit={(e) => {
                        void handleSubmit(e);
                    }}
                />
            </CardContent>
        </Card>
    );
}

export function AdminUserManagement({
    users: initialUsers = [],
}: {
    users?: AdminUser[];
}) {
    const [users, setUsers] = useState<AdminUser[]>(initialUsers);
    const [isCreating, setIsCreating] = useState(false);
    const [createFormData, setCreateFormData] = useState<UserForm>(emptyUserForm);
    const [isSubmittingCreate, setIsSubmittingCreate] = useState(false);
    const [createError, setCreateError] = useState<string | undefined>();
    const [editingUser, setEditingUser] = useState<AdminUser | null>(null);
    const [editFormData, setEditFormData] = useState<UserForm>(emptyUserForm);
    const [isEditing, setIsEditing] = useState(false);
    const [editError, setEditError] = useState<string | undefined>();
    const [filterForm, setFilterForm] = useState<UserFilterForm>({
        email: '',
        name: '',
        role: 'all',
    });

    const userStats = useMemo(() => {
        const adminCount = users.filter((user) => user.role === 'admin').length;

        return {
            adminCount,
            total: users.length,
        };
    }, [users]);

    const filteredUsers = useMemo(() => {
        return users.filter((user) => {
            const nameMatch =
                filterForm.name === '' ||
                (user.name ?? '').toLowerCase().includes(filterForm.name.toLowerCase());
            const emailMatch =
                filterForm.email === '' ||
                (user.email ?? '').toLowerCase().includes(filterForm.email.toLowerCase());
            const roleMatch =
                filterForm.role === 'all' || user.role === filterForm.role;

            return nameMatch && emailMatch && roleMatch;
        });
    }, [users, filterForm]);

    function setCreateField<K extends keyof UserForm>(
        key: K,
        value: UserForm[K],
    ): void {
        setCreateFormData((prev) => ({ ...prev, [key]: value }));
    }

    function setEditField<K extends keyof UserForm>(
        key: K,
        value: UserForm[K],
    ): void {
        setEditFormData((prev) => ({ ...prev, [key]: value }));
    }

    function openEditUserDialog(user: AdminUser): void {
        setEditingUser(user);
        setEditFormData(userToForm(user));
        setEditError(undefined);
    }

    async function handleCreateUser(
        event: FormEvent<HTMLFormElement>,
    ): Promise<void> {
        event.preventDefault();
        setIsSubmittingCreate(true);
        setCreateError(undefined);

        try {
            const payload = buildCreatePayload(createFormData);
            const created = await createAdminUser(payload);
            setUsers((prev) => [created, ...prev]);
            setCreateFormData(emptyUserForm);
            setIsCreating(false);
        } catch (e) {
            setCreateError(
                e instanceof Error ? e.message : 'Gagal membuat user.',
            );
        } finally {
            setIsSubmittingCreate(false);
        }
    }

    async function handleUpdateUser(
        event: FormEvent<HTMLFormElement>,
    ): Promise<void> {
        event.preventDefault();

        if (!editingUser) {
            return;
        }

        setIsEditing(true);
        setEditError(undefined);

        try {
            const payload = buildUpdatePayload(editFormData);
            const updated = await updateAdminUser(editingUser.id, payload);
            setUsers((prev) =>
                prev.map((u) => (u.id === updated.id ? updated : u)),
            );
            setEditingUser(null);
        } catch (e) {
            setEditError(
                e instanceof Error ? e.message : 'Gagal memperbarui user.',
            );
        } finally {
            setIsEditing(false);
        }
    }

    const [deletingUser, setDeletingUser] = useState<AdminUser | null>(null);
    const [isDeleting, setIsDeleting] = useState(false);

    async function handleDeleteUser(): Promise<void> {
        if (!deletingUser) return;
        setIsDeleting(true);
        try {
            await deleteAdminUser(deletingUser.id);
            window.location.reload();
        } catch (e) {
            toast.error(
                e instanceof Error ? e.message : 'Gagal menghapus user.',
            );
            setIsDeleting(false);
        }
    }

    return (
        <>
            <Card className="border-(--lecturer-border) bg-(--lecturer-surface)">
                <CardHeader>
                    <div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
                        <div>
                            <CardTitle>User Management</CardTitle>
                            <CardDescription>
                                Total {userStats.total} user,{' '}
                                {userStats.adminCount} admin.
                            </CardDescription>
                        </div>

                        <div className="flex flex-col gap-2">
                        <div className="flex justify-end">
                            <Button
                                onClick={() => {
                                    setCreateFormData(emptyUserForm);
                                    setCreateError(undefined);
                                    setIsCreating(true);
                                }}
                                type="button"
                            >
                                <Plus className="size-4" />
                                Tambah User
                            </Button>
                        </div>
                        <div className="grid gap-2 sm:grid-cols-[1fr_1fr_160px]">
                            <Input
                                placeholder="Cari nama..."
                                value={filterForm.name}
                                onChange={(event) =>
                                    setFilterForm((prev) => ({
                                        ...prev,
                                        name: event.target.value,
                                    }))
                                }
                            />
                            <Input
                                placeholder="Cari email..."
                                value={filterForm.email}
                                onChange={(event) =>
                                    setFilterForm((prev) => ({
                                        ...prev,
                                        email: event.target.value,
                                    }))
                                }
                            />
                            <Select
                                value={filterForm.role}
                                onValueChange={(value) =>
                                    setFilterForm((prev) => ({
                                        ...prev,
                                        role: value as UserFilterForm['role'],
                                    }))
                                }
                            >
                                <SelectTrigger className="w-full">
                                    <SelectValue placeholder="Role" />
                                </SelectTrigger>
                                <SelectContent>
                                    <SelectItem value="all">
                                        Semua role
                                    </SelectItem>
                                    <SelectItem value="student">
                                        Mahasiswa
                                    </SelectItem>
                                    <SelectItem value="lecturer">
                                        Dosen
                                    </SelectItem>
                                    <SelectItem value="admin">Admin</SelectItem>
                                </SelectContent>
                            </Select>
                        </div>
                        </div>
                    </div>
                </CardHeader>
                <CardContent>
                    <div className="overflow-hidden rounded-xl border border-(--lecturer-border)">
                        <div className="overflow-x-auto">
                            <table className="w-full min-w-190 text-sm">
                                <thead className="bg-muted/50 text-left text-muted-foreground">
                                    <tr>
                                        <th className="px-4 py-3">Nama</th>
                                        <th className="px-4 py-3">Role</th>
                                        <th className="px-4 py-3">Status</th>
                                        <th className="px-4 py-3">
                                            Superuser
                                        </th>
                                        <th className="px-4 py-3">Dibuat</th>
                                        <th className="px-4 py-3 text-right">
                                            Aksi
                                        </th>
                                    </tr>
                                </thead>
                                <tbody>
                                    {filteredUsers.map((user) => (
                                        <tr
                                            className="border-t border-(--lecturer-border)"
                                            key={user.id}
                                        >
                                            <td className="px-4 py-3">
                                                <div className="font-medium">
                                                    {user.name ?? '-'}
                                                </div>
                                                <div className="text-muted-foreground">
                                                    {user.email ?? '-'}
                                                </div>
                                            </td>
                                            <td className="px-4 py-3">
                                                <Badge variant="outline">
                                                    {roleLabel(user.role)}
                                                </Badge>
                                            </td>
                                            <td className="px-4 py-3">
                                                <Badge
                                                    className={
                                                        isUserActive(user)
                                                            ? 'bg-(--lecturer-primary-soft) text-(--lecturer-primary)'
                                                            : ''
                                                    }
                                                    variant={
                                                        isUserActive(user)
                                                            ? 'secondary'
                                                            : 'outline'
                                                    }
                                                >
                                                    {isUserActive(user)
                                                        ? 'Aktif'
                                                        : 'Nonaktif'}
                                                </Badge>
                                            </td>
                                            <td className="px-4 py-3">
                                                {user.is_superuser
                                                    ? 'Ya'
                                                    : 'Tidak'}
                                            </td>
                                            <td className="px-4 py-3">
                                                {formatDate(user.created_at)}
                                            </td>
                                            <td className="px-4 py-3">
                                                <div className="flex justify-end gap-2">
                                                    <Button
                                                        onClick={() =>
                                                            openEditUserDialog(
                                                                user,
                                                            )
                                                        }
                                                        size="sm"
                                                        type="button"
                                                        variant="outline"
                                                    >
                                                        Edit
                                                    </Button>
                                                    <Button
                                                        className="text-destructive hover:text-destructive"
                                                        onClick={() => setDeletingUser(user)}
                                                        size="sm"
                                                        type="button"
                                                        variant="outline"
                                                    >
                                                        <Trash2 className="size-4" />
                                                    </Button>
                                                </div>
                                            </td>
                                        </tr>
                                    ))}

                                    {filteredUsers.length === 0 ? (
                                        <tr>
                                            <td
                                                className="px-4 py-8 text-center text-muted-foreground"
                                                colSpan={6}
                                            >
                                                {users.length === 0
                                                    ? 'Tidak ada user dari response backend.'
                                                    : 'Tidak ada user yang cocok dengan filter.'}
                                            </td>
                                        </tr>
                                    ) : null}
                                </tbody>
                            </table>
                        </div>
                    </div>
                </CardContent>
            </Card>

            <Dialog onOpenChange={setIsCreating} open={isCreating}>
                <DialogContent className="max-w-2xl">
                    <DialogHeader>
                        <DialogTitle>Tambah User</DialogTitle>
                        <DialogDescription>
                            Payload mengikuti schema UpsertUser dari API.
                        </DialogDescription>
                    </DialogHeader>

                    <UserFormFields
                        data={createFormData}
                        error={createError}
                        isSubmitting={isSubmittingCreate}
                        setField={setCreateField}
                        submitLabel="Buat User"
                        onSubmit={(e) => {
                            void handleCreateUser(e);
                        }}
                    />
                </DialogContent>
            </Dialog>

            <Dialog
                onOpenChange={(open) => setEditingUser(open ? editingUser : null)}
                open={editingUser !== null}
            >
                <DialogContent className="max-w-2xl">
                    <DialogHeader>
                        <DialogTitle>Edit User</DialogTitle>
                        <DialogDescription>
                            Perubahan dikirim ke endpoint update user backend.
                        </DialogDescription>
                    </DialogHeader>

                    <UserFormFields
                        data={editFormData}
                        error={editError}
                        isSubmitting={isEditing}
                        mode="edit"
                        setField={setEditField}
                        submitLabel="Simpan User"
                        onSubmit={(e) => {
                            void handleUpdateUser(e);
                        }}
                    />
                </DialogContent>
            </Dialog>

            <Dialog
                open={deletingUser !== null}
                onOpenChange={(open) => { if (!open) setDeletingUser(null); }}
            >
                <DialogContent>
                    <DialogHeader>
                        <DialogTitle>Hapus user?</DialogTitle>
                        <DialogDescription>
                            Akun <span className="font-medium">{deletingUser?.email ?? '-'}</span> akan dihapus permanen dan tidak bisa dikembalikan.
                        </DialogDescription>
                    </DialogHeader>
                    <DialogFooter>
                        <Button
                            onClick={() => setDeletingUser(null)}
                            type="button"
                            variant="outline"
                            disabled={isDeleting}
                        >
                            Batal
                        </Button>
                        <Button
                            className="bg-destructive text-white hover:bg-destructive/90"
                            disabled={isDeleting}
                            onClick={() => { void handleDeleteUser(); }}
                            type="button"
                        >
                            {isDeleting ? <Spinner className="size-4" /> : null}
                            Hapus
                        </Button>
                    </DialogFooter>
                </DialogContent>
            </Dialog>
        </>
    );
}

function buildCreatePayload(form: UserForm): Record<string, unknown> {
    // POST /auth/register — RegisterRequest schema
    const payload: Record<string, unknown> = { role: form.role };
    if (form.email) payload.email = form.email;
    if (form.name) payload.name = form.name;
    if (form.password) payload.password = form.password;
    if (form.identity_number) payload.identity_number = form.identity_number;
    if (form.phone) payload.phone = form.phone;
    return payload;
}

function buildUpdatePayload(form: UserForm): Record<string, unknown> {
    // PATCH /user/{id} — PatchUser schema (additionalProperties: false)
    // Only: email, name, phone, role, is_active, password
    const payload: Record<string, unknown> = {
        is_active: form.is_active,
        role: form.role,
    };
    if (form.email) payload.email = form.email;
    if (form.name) payload.name = form.name;
    if (form.phone) payload.phone = form.phone;
    if (form.password) payload.password = form.password;
    return payload;
}

function UserFormFields({
    data,
    error,
    isSubmitting,
    mode = 'create',
    onSubmit,
    setField,
    submitLabel,
}: {
    data: UserForm;
    error?: string;
    isSubmitting: boolean;
    mode?: 'create' | 'edit';
    onSubmit: (event: FormEvent<HTMLFormElement>) => void;
    setField: <K extends keyof UserForm>(key: K, value: UserForm[K]) => void;
    submitLabel: string;
}) {
    const [showPassword, setShowPassword] = useState(false);

    return (
        <form className="grid gap-4" onSubmit={onSubmit}>
            <ConfigError message={error} />

            <div className="grid gap-3 md:grid-cols-2">
                <Field label="Nama">
                    <Input
                        value={data.name}
                        onChange={(event) =>
                            setField('name', event.target.value)
                        }
                    />
                </Field>
                <Field label="Email">
                    <Input
                        type="email"
                        value={data.email}
                        onChange={(event) =>
                            setField('email', event.target.value)
                        }
                    />
                </Field>
                <Field
                    hint={
                        mode === 'edit'
                            ? 'Kosongkan jika tidak ingin mengubah password.'
                            : 'Password untuk login user.'
                    }
                    label="Password"
                >
                    <div className="relative">
                        <Input
                            autoComplete="off"
                            className="pr-10"
                            placeholder={mode === 'edit' ? '(tidak diubah)' : '••••••••'}
                            type={showPassword ? 'text' : 'password'}
                            value={data.password}
                            onChange={(event) =>
                                setField('password', event.target.value)
                            }
                        />
                        <button
                            className="text-muted-foreground hover:text-foreground absolute right-3 top-1/2 -translate-y-1/2"
                            type="button"
                            onClick={() => setShowPassword((v) => !v)}
                        >
                            {showPassword ? (
                                <EyeOff className="size-4" />
                            ) : (
                                <Eye className="size-4" />
                            )}
                        </button>
                    </div>
                </Field>
                <Field label="Nomor Identitas">
                    <Input
                        value={data.identity_number}
                        onChange={(event) =>
                            setField('identity_number', event.target.value)
                        }
                    />
                </Field>
                <Field label="Telepon">
                    <Input
                        value={data.phone}
                        onChange={(event) =>
                            setField('phone', event.target.value)
                        }
                    />
                </Field>
                <Field label="Role">
                    <Select
                        value={data.role}
                        onValueChange={(value) =>
                            setField('role', value as AdminRole)
                        }
                    >
                        <SelectTrigger className="w-full">
                            <SelectValue placeholder="Pilih role" />
                        </SelectTrigger>
                        <SelectContent>
                            <SelectItem value="student">Mahasiswa</SelectItem>
                            <SelectItem value="lecturer">Dosen</SelectItem>
                            <SelectItem value="admin">Admin</SelectItem>
                        </SelectContent>
                    </Select>
                </Field>
            </div>

            <div className="grid gap-3 sm:grid-cols-2">
                <label className="flex items-center gap-3 rounded-lg border border-(--lecturer-border) p-3 text-sm">
                    <Checkbox
                        checked={data.is_active}
                        onCheckedChange={(value) =>
                            setField('is_active', value === true)
                        }
                    />
                    <span className="flex items-center gap-1.5">
                        User aktif
                        <InfoHint>
                            User dapat login dan menggunakan sistem. Nonaktifkan untuk memblokir akses tanpa menghapus akun.
                        </InfoHint>
                    </span>
                </label>
                <label className="flex items-center gap-3 rounded-lg border border-(--lecturer-border) p-3 text-sm">
                    <Checkbox
                        checked={data.is_superuser}
                        onCheckedChange={(value) =>
                            setField('is_superuser', value === true)
                        }
                    />
                    <span className="flex items-center gap-1.5">
                        Superuser
                        <InfoHint>
                            Memiliki hak akses penuh ke semua fitur sistem tanpa pembatasan role.
                        </InfoHint>
                    </span>
                </label>
            </div>

            <div className="flex justify-end">
                <Button disabled={isSubmitting} type="submit">
                    {isSubmitting ? <Spinner className="size-4" /> : null}
                    {submitLabel}
                </Button>
            </div>
        </form>
    );
}

