import { Form, Head } from '@inertiajs/react';
import DepartmentController from '@/actions/App/Http/Controllers/Admin/DepartmentController';
import UserManagementController from '@/actions/App/Http/Controllers/Admin/UserManagementController';
import Heading from '@/components/heading';
import InputError from '@/components/input-error';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
import {
    Dialog,
    DialogClose,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
    DialogTrigger,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Building2, ChevronDown, Trash2, UserPlus } from 'lucide-react';
import { Fragment, useState } from 'react';

type Department = {
    id: number;
    name: string;
};

type AdminUser = {
    id: number;
    name: string;
    email: string;
    role: string;
    created_at: string | null;
    departments: Department[];
    can_edit: boolean;
    can_delete: boolean;
};

function formatRole(role: string): string {
    return role
        .split('_')
        .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
        .join(' ');
}

function DepartmentChecklist({
    departments,
    selectedDepartmentIds = [],
}: {
    departments: Department[];
    selectedDepartmentIds?: number[];
}) {
    if (departments.length === 0) {
        return (
            <div className="rounded-lg border border-dashed p-4 text-sm text-muted-foreground">
                No departments are available yet.
            </div>
        );
    }

    return (
        <div className="space-y-2 rounded-lg border p-3">
            {departments.map((department) => (
                <label
                    key={department.id}
                    className="flex items-center gap-3 rounded-md px-2 py-1 text-sm"
                >
                    <input
                        type="checkbox"
                        name="department_ids[]"
                        value={department.id}
                        defaultChecked={selectedDepartmentIds.includes(department.id)}
                        className="size-4 rounded border-input"
                    />
                    <span>{department.name}</span>
                </label>
            ))}
        </div>
    );
}

function AddDepartmentDialog() {
    return (
        <Dialog>
            <DialogTrigger asChild>
                <Button type="button" variant="outline">
                    <Building2 />
                    Add department
                </Button>
            </DialogTrigger>
            <DialogContent>
                <DialogHeader>
                    <DialogTitle>Add department</DialogTitle>
                    <DialogDescription>
                        Departments control which users and sensors can see each other.
                    </DialogDescription>
                </DialogHeader>

                <Form
                    {...DepartmentController.store.form()}
                    resetOnSuccess={['name']}
                    className="space-y-4"
                >
                    {({ processing, errors }) => (
                        <>
                            <div className="grid gap-2">
                                <Label htmlFor="department-name">Department name</Label>
                                <Input
                                    id="department-name"
                                    name="name"
                                    placeholder="Operations"
                                    required
                                />
                                <InputError message={errors.name} />
                            </div>

                            <DialogFooter>
                                <DialogClose asChild>
                                    <Button type="button" variant="outline">
                                        Cancel
                                    </Button>
                                </DialogClose>
                                <Button type="submit" disabled={processing}>
                                    Add department
                                </Button>
                            </DialogFooter>
                        </>
                    )}
                </Form>
            </DialogContent>
        </Dialog>
    );
}

function AddUserDialog({
    roles,
    departments,
    canManageAssignments,
}: {
    roles: string[];
    departments: Department[];
    canManageAssignments: boolean;
}) {
    return (
        <Dialog>
            <DialogTrigger asChild>
                <Button type="button">
                    <UserPlus />
                    Add user
                </Button>
            </DialogTrigger>
            <DialogContent className="max-h-[calc(100vh-2rem)] overflow-y-auto">
                <DialogHeader>
                    <DialogTitle>Add user</DialogTitle>
                    <DialogDescription>
                        Super users can only create regular users inside the departments they
                        manage.
                    </DialogDescription>
                </DialogHeader>

                <Form
                    {...UserManagementController.store.form()}
                    resetOnSuccess={[
                        'name',
                        'email',
                        'password',
                        'password_confirmation',
                    ]}
                    className="space-y-4"
                >
                    {({ processing, errors }) => (
                        <>
                            <div className="grid gap-2">
                                <Label htmlFor="name">Name</Label>
                                <Input
                                    id="name"
                                    name="name"
                                    placeholder="Full name"
                                    required
                                />
                                <InputError message={errors.name} />
                            </div>

                            <div className="grid gap-2">
                                <Label htmlFor="email">Email address</Label>
                                <Input
                                    id="email"
                                    type="email"
                                    name="email"
                                    placeholder="name@example.com"
                                    required
                                />
                                <InputError message={errors.email} />
                            </div>

                            <div className="grid gap-2">
                                <Label htmlFor="role">Role</Label>
                                <select
                                    id="role"
                                    name="role"
                                    defaultValue={roles.includes('user') ? 'user' : roles[0]}
                                    className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs outline-none transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]"
                                >
                                    {roles.map((role) => (
                                        <option key={role} value={role}>
                                            {formatRole(role)}
                                        </option>
                                    ))}
                                </select>
                                <InputError message={errors.role} />
                            </div>

                            <div className="grid gap-2">
                                <Label>Departments</Label>
                                <DepartmentChecklist departments={departments} />
                                <InputError message={errors.department_ids} />
                            </div>

                            <div className="grid gap-2">
                                <Label htmlFor="password">Password</Label>
                                <Input
                                    id="password"
                                    type="password"
                                    name="password"
                                    placeholder="Temporary password"
                                    required
                                />
                                <InputError message={errors.password} />
                            </div>

                            <div className="grid gap-2">
                                <Label htmlFor="password_confirmation">Confirm password</Label>
                                <Input
                                    id="password_confirmation"
                                    type="password"
                                    name="password_confirmation"
                                    placeholder="Repeat password"
                                    required
                                />
                            </div>

                            <DialogFooter>
                                <DialogClose asChild>
                                    <Button type="button" variant="outline">
                                        Cancel
                                    </Button>
                                </DialogClose>
                                <Button
                                    type="submit"
                                    disabled={processing || !canManageAssignments}
                                >
                                    Add user
                                </Button>
                            </DialogFooter>
                        </>
                    )}
                </Form>
            </DialogContent>
        </Dialog>
    );
}

export default function Users({
    users,
    roles,
    departments,
    canCreateDepartments,
}: {
    users: AdminUser[];
    roles: string[];
    departments: Department[];
    canCreateDepartments: boolean;
}) {
    const canManageAssignments = departments.length > 0;
    const [expandedUserId, setExpandedUserId] = useState<number | null>(null);

    function toggleExpandedUser(userId: number): void {
        setExpandedUserId((currentUserId) =>
            currentUserId === userId ? null : userId,
        );
    }

    return (
        <>
            <Head title="Admin users" />

            <div className="space-y-6 p-4">
                <Heading
                    title="User management"
                    description="Create departments, assign department managers, and keep users limited to the departments they belong to."
                />

                <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end">
                    {canCreateDepartments ? <AddDepartmentDialog /> : null}
                    <AddUserDialog
                        roles={roles}
                        departments={departments}
                        canManageAssignments={canManageAssignments}
                    />
                </div>

                <div className="w-full">
                    <Card>
                        <CardHeader>
                            <CardTitle>Existing users</CardTitle>
                            <CardDescription>
                                Main admin is view-only. Department assignments can be updated for
                                everyone else you are allowed to manage.
                            </CardDescription>
                        </CardHeader>
                        <CardContent>
                            {users.length === 0 ? (
                                <div className="rounded-lg border border-dashed p-6 text-sm text-muted-foreground">
                                    No users have been created yet.
                                </div>
                            ) : (
                                <div className="overflow-x-auto rounded-md border">
                                    <table className="w-full min-w-[900px] table-auto text-sm">
                                        <thead className="bg-muted/50 text-left text-xs font-medium uppercase tracking-wide text-muted-foreground">
                                            <tr>
                                                <th className="px-4 py-3">User</th>
                                                <th className="px-4 py-3">Role</th>
                                                <th className="px-4 py-3">Departments</th>
                                                <th className="px-4 py-3">Added</th>
                                                <th className="px-4 py-3 text-right">Actions</th>
                                            </tr>
                                        </thead>
                                        <tbody className="divide-y">
                                            {users.map((user) => (
                                                <Fragment key={user.id}>
                                                    <tr className="align-middle">
                                                        <td className="px-4 py-4">
                                                            <div className="font-medium">
                                                                {user.name}
                                                            </div>
                                                            <div className="mt-1 text-sm text-muted-foreground">
                                                                {user.email}
                                                            </div>
                                                        </td>
                                                        <td className="px-4 py-4">
                                                            <Badge
                                                                variant={
                                                                    user.role === 'admin'
                                                                        ? 'default'
                                                                        : 'secondary'
                                                                }
                                                            >
                                                                {formatRole(user.role)}
                                                            </Badge>
                                                        </td>
                                                        <td className="max-w-[22rem] px-4 py-4">
                                                            {user.departments.length > 0 ? (
                                                                <div className="flex flex-wrap gap-2">
                                                                    {user.departments.map(
                                                                        (department) => (
                                                                            <Badge
                                                                                key={
                                                                                    department.id
                                                                                }
                                                                                variant="outline"
                                                                            >
                                                                                {department.name}
                                                                            </Badge>
                                                                        ),
                                                                    )}
                                                                </div>
                                                            ) : (
                                                                <span className="text-muted-foreground">
                                                                    None
                                                                </span>
                                                            )}
                                                        </td>
                                                        <td className="whitespace-nowrap px-4 py-4 text-muted-foreground">
                                                            {user.created_at ?? 'Recently'}
                                                        </td>
                                                        <td className="px-4 py-4">
                                                            <div className="flex justify-end gap-2">
                                                                {user.can_edit ? (
                                                                    <Button
                                                                        type="button"
                                                                        variant="outline"
                                                                        size="sm"
                                                                        onClick={() =>
                                                                            toggleExpandedUser(
                                                                                user.id,
                                                                            )
                                                                        }
                                                                        aria-expanded={
                                                                            expandedUserId ===
                                                                            user.id
                                                                        }
                                                                    >
                                                                        <ChevronDown
                                                                            className={
                                                                                expandedUserId ===
                                                                                user.id
                                                                                    ? 'rotate-180'
                                                                                    : ''
                                                                            }
                                                                        />
                                                                        Edit
                                                                    </Button>
                                                                ) : (
                                                                    <span className="rounded-md bg-muted px-3 py-1.5 text-sm text-muted-foreground">
                                                                        Locked
                                                                    </span>
                                                                )}

                                                                {user.can_delete ? (
                                                                    <Dialog>
                                                                        <DialogTrigger asChild>
                                                                            <Button
                                                                                type="button"
                                                                                variant="destructive"
                                                                                size="sm"
                                                                            >
                                                                                <Trash2 />
                                                                                Delete
                                                                            </Button>
                                                                        </DialogTrigger>
                                                                        <DialogContent>
                                                                            <DialogHeader>
                                                                                <DialogTitle>
                                                                                    Delete{' '}
                                                                                    {user.name}?
                                                                                </DialogTitle>
                                                                                <DialogDescription>
                                                                                    This removes
                                                                                    the user
                                                                                    account and
                                                                                    its department
                                                                                    assignments.
                                                                                    This action
                                                                                    cannot be
                                                                                    undone.
                                                                                </DialogDescription>
                                                                            </DialogHeader>

                                                                            <DialogFooter>
                                                                                <DialogClose asChild>
                                                                                    <Button
                                                                                        type="button"
                                                                                        variant="outline"
                                                                                    >
                                                                                        Cancel
                                                                                    </Button>
                                                                                </DialogClose>
                                                                                <Form
                                                                                    {...UserManagementController.destroy.form(
                                                                                        user.id,
                                                                                    )}
                                                                                >
                                                                                    {({
                                                                                        processing,
                                                                                    }) => (
                                                                                        <Button
                                                                                            type="submit"
                                                                                            variant="destructive"
                                                                                            disabled={
                                                                                                processing
                                                                                            }
                                                                                        >
                                                                                            Delete
                                                                                            user
                                                                                        </Button>
                                                                                    )}
                                                                                </Form>
                                                                            </DialogFooter>
                                                                        </DialogContent>
                                                                    </Dialog>
                                                                ) : null}
                                                            </div>
                                                        </td>
                                                    </tr>

                                                    {expandedUserId === user.id ? (
                                                        <tr className="bg-muted/20">
                                                            <td colSpan={5} className="px-4 py-4">
                                                                <Form
                                                                    {...UserManagementController.update.form(
                                                                        user.id,
                                                                    )}
                                                                    className="grid gap-4 lg:grid-cols-[minmax(12rem,18rem)_minmax(18rem,1fr)_auto] lg:items-end"
                                                                >
                                                                    {({ processing, errors }) => (
                                                                        <>
                                                                            <div className="grid gap-2">
                                                                                <Label
                                                                                    htmlFor={`edit-role-${user.id}`}
                                                                                >
                                                                                    Role
                                                                                </Label>
                                                                                <select
                                                                                    id={`edit-role-${user.id}`}
                                                                                    name="role"
                                                                                    defaultValue={
                                                                                        user.role
                                                                                    }
                                                                                    className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-xs outline-none transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]"
                                                                                >
                                                                                    {roles.map(
                                                                                        (role) => (
                                                                                            <option
                                                                                                key={
                                                                                                    role
                                                                                                }
                                                                                                value={
                                                                                                    role
                                                                                                }
                                                                                            >
                                                                                                {formatRole(
                                                                                                    role,
                                                                                                )}
                                                                                            </option>
                                                                                        ),
                                                                                    )}
                                                                                </select>
                                                                                <InputError
                                                                                    message={
                                                                                        errors.role
                                                                                    }
                                                                                />
                                                                            </div>

                                                                            <div className="grid gap-2">
                                                                                <Label>
                                                                                    Departments
                                                                                </Label>
                                                                                <DepartmentChecklist
                                                                                    departments={
                                                                                        departments
                                                                                    }
                                                                                    selectedDepartmentIds={user.departments.map(
                                                                                        (
                                                                                            department,
                                                                                        ) =>
                                                                                            department.id,
                                                                                    )}
                                                                                />
                                                                                <InputError
                                                                                    message={
                                                                                        errors.department_ids
                                                                                    }
                                                                                />
                                                                            </div>

                                                                            <div className="flex gap-2">
                                                                                <Button
                                                                                    type="button"
                                                                                    variant="outline"
                                                                                    size="sm"
                                                                                    onClick={() =>
                                                                                        setExpandedUserId(
                                                                                            null,
                                                                                        )
                                                                                    }
                                                                                >
                                                                                    Cancel
                                                                                </Button>
                                                                                <Button
                                                                                    type="submit"
                                                                                    size="sm"
                                                                                    disabled={
                                                                                        processing ||
                                                                                        !canManageAssignments
                                                                                    }
                                                                                >
                                                                                    Save
                                                                                </Button>
                                                                            </div>
                                                                        </>
                                                                    )}
                                                                </Form>
                                                            </td>
                                                        </tr>
                                                    ) : null}
                                                </Fragment>
                                            ))}
                                        </tbody>
                                    </table>
                                </div>
                            )}
                        </CardContent>
                    </Card>
                </div>
            </div>
        </>
    );
}

Users.layout = {
    breadcrumbs: [
        {
            title: 'Admin users',
            href: UserManagementController.index(),
        },
    ],
};
