import { useForm } from '@inertiajs/react';
import { Plus, Trash2, UserRoundX, Users } from 'lucide-react';
import React, { useState } from 'react';

import { syncMembers } from '@/actions/App/Domains/Shared/Http/Controllers/Admin/DivisionController';

import { ConfirmActionDialog } from '@/components/ConfirmActionDialog';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import type { AdminDivision, UserOption } from '@/types/admin';

/** Satu baris form; user_id 0 berarti belum dipilih. */
interface MemberDraft {
    user_id: number;
    role_type: string;
    role_label: string;
}

interface DivisionMembersDialogProps {
    division: AdminDivision | null;
    users: UserOption[];
    divisionRoleOptions: string[];
    open: boolean;
    onOpenChange: (open: boolean) => void;
}

export function DivisionMembersDialog({
    division,
    users,
    divisionRoleOptions,
    open,
    onOpenChange,
}: DivisionMembersDialogProps) {
    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="flex max-h-[calc(100dvh-4rem)] flex-col sm:max-w-215 [&>button:last-child]:hidden">
                {division && (
                    <DivisionMembersForm
                        key={division.id}
                        division={division}
                        users={users}
                        divisionRoleOptions={divisionRoleOptions}
                        onClose={() => onOpenChange(false)}
                    />
                )}
            </DialogContent>
        </Dialog>
    );
}

function DivisionMembersForm({
    division,
    users,
    divisionRoleOptions,
    onClose,
}: {
    division: AdminDivision;
    users: UserOption[];
    divisionRoleOptions: string[];
    onClose: () => void;
}) {
    const [pendingRemoval, setPendingRemoval] = useState<number | null>(null);

    const { data, setData, put, processing, errors } = useForm<{
        members: MemberDraft[];
    }>({
        members: division.members.map((member) => ({
            user_id: member.user_id,
            role_type: member.role_type,
            role_label: member.role_label ?? '',
        })),
    });

    // Error validasi bersarang datang dengan key seperti "members.0.user_id",
    // yang tidak tercakup tipe errors bawaan.
    const nestedErrors = errors as unknown as Record<string, string>;

    const takenUserIds = new Set(data.members.map((member) => member.user_id));

    const updateRow = (index: number, patch: Partial<MemberDraft>) => {
        setData(
            'members',
            data.members.map((member, position) =>
                position === index ? { ...member, ...patch } : member,
            ),
        );
    };

    const addRow = () => {
        setData('members', [
            ...data.members,
            {
                user_id: 0,
                role_type: divisionRoleOptions[0] ?? 'member',
                role_label: '',
            },
        ]);
    };

    const removeRow = (index: number) => {
        setData(
            'members',
            data.members.filter((_, position) => position !== index),
        );
    };

    /**
     * Mengeluarkan anggota memutus aksesnya ke seluruh isi divisi, jadi baris
     * yang sudah menunjuk user nyata dikonfirmasi dulu. Baris kosong yang baru
     * ditambah tidak perlu — belum ada yang hilang.
     */
    const requestRemoval = (index: number) => {
        if (data.members[index].user_id === 0) {
            removeRow(index);

            return;
        }

        setPendingRemoval(index);
    };

    const pendingMember =
        pendingRemoval === null ? null : data.members[pendingRemoval];

    const pendingMemberName = users.find(
        (user) => user.id === pendingMember?.user_id,
    )?.name;

    const handleSubmit = (e: React.FormEvent) => {
        e.preventDefault();

        put(syncMembers({ division: division.slug }).url, {
            preserveScroll: true,
            onSuccess: onClose,
        });
    };

    return (
        <>
            <DialogHeader>
                <DialogTitle className="flex items-center gap-2">
                    <Users className="h-5 w-5" />
                    Division Members
                </DialogTitle>
                <DialogDescription>
                    Map users to{' '}
                    <span className="font-medium text-foreground">
                        {division.name}
                    </span>
                    . Removing a row revokes that membership.
                </DialogDescription>
            </DialogHeader>

            <form
                onSubmit={handleSubmit}
                className="flex min-h-0 flex-1 flex-col"
            >
                <div className="min-h-0 flex-1 space-y-3 overflow-y-auto py-4">
                    {/* Penolakan pelepasan anggota (K9) datang sebagai error
                        pada atribut induk, bukan pada baris mana pun — tanpa
                        blok ini penolakannya tidak terlihat sama sekali. */}
                    {nestedErrors.members && (
                        <p className="rounded-lg border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive">
                            {nestedErrors.members}
                        </p>
                    )}

                    {data.members.length === 0 && (
                        <p className="rounded-lg border border-dashed px-4 py-8 text-center text-sm text-muted-foreground">
                            This division has no member yet.
                        </p>
                    )}

                    {data.members.map((member, index) => (
                        <div
                            key={index}
                            className="grid gap-3 rounded-lg border bg-muted/30 p-3 sm:grid-cols-[minmax(0,1.2fr)_11rem_minmax(0,1.4fr)_auto]"
                        >
                            <div className="space-y-1.5">
                                <Label
                                    className="text-xs text-muted-foreground"
                                    htmlFor={`member-user-${index}`}
                                >
                                    User
                                </Label>
                                <Select
                                    value={
                                        member.user_id === 0
                                            ? ''
                                            : String(member.user_id)
                                    }
                                    onValueChange={(value) =>
                                        updateRow(index, {
                                            user_id: Number(value),
                                        })
                                    }
                                >
                                    <SelectTrigger
                                        id={`member-user-${index}`}
                                        className="w-full"
                                    >
                                        <SelectValue placeholder="Select user" />
                                    </SelectTrigger>
                                    <SelectContent>
                                        {users.map((user) => (
                                            <SelectItem
                                                key={user.id}
                                                value={String(user.id)}
                                                disabled={
                                                    user.id !==
                                                        member.user_id &&
                                                    takenUserIds.has(user.id)
                                                }
                                            >
                                                {user.name}
                                                {user.nik && (
                                                    <span className="text-muted-foreground">
                                                        {' '}
                                                        · {user.nik}
                                                    </span>
                                                )}
                                            </SelectItem>
                                        ))}
                                    </SelectContent>
                                </Select>
                                {nestedErrors[`members.${index}.user_id`] && (
                                    <p className="text-xs text-destructive">
                                        {
                                            nestedErrors[
                                                `members.${index}.user_id`
                                            ]
                                        }
                                    </p>
                                )}
                            </div>

                            <div className="space-y-1.5">
                                <Label
                                    className="text-xs text-muted-foreground"
                                    htmlFor={`member-role-${index}`}
                                >
                                    Role
                                </Label>
                                <Select
                                    value={member.role_type}
                                    onValueChange={(value) =>
                                        updateRow(index, { role_type: value })
                                    }
                                >
                                    <SelectTrigger
                                        id={`member-role-${index}`}
                                        className="w-full capitalize"
                                    >
                                        <SelectValue />
                                    </SelectTrigger>
                                    <SelectContent>
                                        {divisionRoleOptions.map((role) => (
                                            <SelectItem
                                                key={role}
                                                value={role}
                                                className="capitalize"
                                            >
                                                {role}
                                            </SelectItem>
                                        ))}
                                    </SelectContent>
                                </Select>
                                {nestedErrors[`members.${index}.role_type`] && (
                                    <p className="text-xs text-destructive">
                                        {
                                            nestedErrors[
                                                `members.${index}.role_type`
                                            ]
                                        }
                                    </p>
                                )}
                            </div>

                            <div className="space-y-1.5">
                                <Label
                                    className="text-xs text-muted-foreground"
                                    htmlFor={`member-label-${index}`}
                                >
                                    Job Title (optional)
                                </Label>
                                <Input
                                    id={`member-label-${index}`}
                                    value={member.role_label}
                                    onChange={(
                                        e: React.ChangeEvent<HTMLInputElement>,
                                    ) =>
                                        updateRow(index, {
                                            role_label: e.target.value,
                                        })
                                    }
                                    placeholder="e.g. Kepala Cabang Jakarta"
                                />
                                {nestedErrors[
                                    `members.${index}.role_label`
                                ] && (
                                    <p className="text-xs text-destructive">
                                        {
                                            nestedErrors[
                                                `members.${index}.role_label`
                                            ]
                                        }
                                    </p>
                                )}
                            </div>

                            <div className="flex items-end">
                                <Button
                                    type="button"
                                    variant="ghost"
                                    size="icon"
                                    aria-label="Remove member"
                                    onClick={() => requestRemoval(index)}
                                >
                                    <Trash2 className="h-4 w-4 text-destructive" />
                                </Button>
                            </div>
                        </div>
                    ))}

                    <Button
                        type="button"
                        variant="outline"
                        onClick={addRow}
                        disabled={data.members.length >= users.length}
                    >
                        <Plus className="mr-1 h-4 w-4" />
                        Add Member
                    </Button>
                </div>

                <DialogFooter className="border-t pt-4">
                    <Button type="button" variant="outline" onClick={onClose}>
                        Cancel
                    </Button>
                    <Button type="submit" disabled={processing}>
                        {processing ? 'Saving...' : 'Save Members'}
                    </Button>
                </DialogFooter>
            </form>

            <ConfirmActionDialog
                open={pendingRemoval !== null}
                onOpenChange={(open) => !open && setPendingRemoval(null)}
                onConfirm={() => {
                    if (pendingRemoval !== null) {
                        removeRow(pendingRemoval);
                    }

                    setPendingRemoval(null);
                }}
                title="Remove this member?"
                description={
                    <>
                        <span className="font-medium text-foreground">
                            {pendingMemberName ?? 'This user'}
                        </span>{' '}
                        will lose access to {division.name} and everything
                        inside it. The change takes effect once you save.
                    </>
                }
                confirmLabel="Remove"
                cancelLabel="Cancel"
                tone="danger"
                icon={UserRoundX}
            />
        </>
    );
}
