import { Head, router, useForm } from '@inertiajs/react';
import {
    CalendarClock,
    CheckCircle2,
    ChevronDown,
    ClipboardList,
    Plus,
    Save,
    UserCheck,
} from 'lucide-react';
import { useEffect, useState } from 'react';
import { Field } from '@/components/crm/form-field';
import { KpiTile } from '@/components/crm/kpi-tile';
import { NativeSelect } from '@/components/crm/native-select';
import { EmptyState, PageHeader } from '@/components/crm/page-header';
import { PriorityBadge, StatusLabel } from '@/components/crm/status-badge';
import {
    FilterBar,
    FilterField,
    SearchInput,
    SegmentedControl,
    TableCard,
} from '@/components/crm/toolbar';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { formatDate } from '@/lib/format';
import { cn } from '@/lib/utils';
import { index as tasksIndex, store, update } from '@/routes/operations/tasks';

type Option = { value: string; label: string };
type StatusOption = Option & { color: string };

type TaskRow = {
    id: number;
    reference: string;
    title: string;
    description: string | null;
    job: { id: number; job_number: string; title: string } | null;
    customer: { id: number; name: string } | null;
    lead: { id: number; lead_number: string; name: string } | null;
    from_department: StatusOption;
    assigned_department: StatusOption;
    owner: { id: number; name: string } | null;
    status: StatusOption;
    priority: { value: string; label: string; color: string };
    due_on: string | null;
    is_overdue: boolean;
    days_until_due: number | null;
    completion_notes: string | null;
};

type Filters = {
    search: string | null;
    department: string | null;
    status: string | null;
    scope: string;
};

export default function Tasks({
    tasks,
    board,
    filters,
    options,
    stats,
    can,
}: {
    tasks: TaskRow[];
    board: Array<{
        department: string;
        label: string;
        color: string;
        count: number;
        tasks: TaskRow[];
    }>;
    filters: Filters;
    options: {
        departments: StatusOption[];
        taskStatuses: StatusOption[];
        priorities: Option[];
        staff: Array<{ value: number; label: string }>;
        customers: Array<{ value: number; label: string }>;
        jobs: Array<{ value: number; label: string }>;
    };
    stats: {
        open: number;
        overdue: number;
        due_today: number;
        completed_this_week: number;
    };
    can: { manage: boolean };
}) {
    const [search, setSearch] = useState(filters.search ?? '');
    const [showCreate, setShowCreate] = useState(false);
    const [completing, setCompleting] = useState<TaskRow | null>(null);
    const [view, setView] = useState<'board' | 'list'>('board');
    const [collapsedDepartments, setCollapsedDepartments] = useState<
        Record<string, boolean>
    >({});

    const toggleDepartment = (department: string): void => {
        setCollapsedDepartments((current) => ({
            ...current,
            [department]: !current[department],
        }));
    };

    useEffect(() => {
        setSearch(filters.search ?? '');
    }, [filters.search]);

    const apply = (changes: Partial<Filters>) => {
        router.get(
            tasksIndex().url,
            { ...filters, ...changes, search: search || null },
            { preserveState: true, preserveScroll: true, replace: true },
        );
    };

    return (
        <>
            <Head title="Operations tasks" />

            <div className="flex flex-col gap-5">
                <PageHeader
                    eyebrow={
                        <>
                            <ClipboardList className="size-3.5 text-solar" />
                            <span>Operations</span>
                        </>
                    }
                    title="Department handovers"
                    description="Work passed between departments, with an owner and a date. A task always names the department it came from, so the person doing the work knows who is waiting."
                    actions={
                        can.manage ? (
                            <Button
                                size="sm"
                                onClick={() => setShowCreate(true)}
                            >
                                <Plus className="size-4" />
                                New task
                            </Button>
                        ) : undefined
                    }
                />

                <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
                    <KpiTile
                        label="Open tasks"
                        value={stats.open}
                        hint="Across every department"
                        icon={ClipboardList}
                        tone="blue"
                    />
                    <KpiTile
                        label="Overdue"
                        value={stats.overdue}
                        hint="Past their due date"
                        icon={CalendarClock}
                        tone={stats.overdue > 0 ? 'danger' : 'slate'}
                        href={tasksIndex({ query: { scope: 'overdue' } }).url}
                    />
                    <KpiTile
                        label="Due today"
                        value={stats.due_today}
                        hint="Needs attention before close"
                        icon={UserCheck}
                        tone={stats.due_today > 0 ? 'warning' : 'slate'}
                    />
                    <KpiTile
                        label="Done this week"
                        value={stats.completed_this_week}
                        hint="Cleared since Monday"
                        icon={CheckCircle2}
                        tone="success"
                        href={tasksIndex({ query: { scope: 'done' } }).url}
                    />
                </div>

                <form
                    onSubmit={(event) => {
                        event.preventDefault();
                        apply({});
                    }}
                >
                    <FilterBar
                        actions={
                            <>
                                <SegmentedControl
                                    value={view}
                                    onChange={setView}
                                    options={[
                                        { value: 'board', label: 'Board' },
                                        { value: 'list', label: 'List' },
                                    ]}
                                />
                                <SegmentedControl
                                    value={filters.scope}
                                    onChange={(scope) => apply({ scope })}
                                    options={[
                                        { value: 'open', label: 'Open' },
                                        { value: 'mine', label: 'Mine' },
                                        { value: 'overdue', label: 'Overdue' },
                                        { value: 'done', label: 'Done' },
                                    ]}
                                />
                            </>
                        }
                    >
                        <SearchInput
                            value={search}
                            onChange={setSearch}
                            placeholder="Reference, title or job"
                        />
                        <FilterField label="Department">
                            <NativeSelect
                                value={filters.department ?? ''}
                                onChange={(event) =>
                                    apply({
                                        department: event.target.value || null,
                                    })
                                }
                                className="h-9 w-40"
                            >
                                <option value="">Any department</option>
                                {options.departments.map((department) => (
                                    <option
                                        key={department.value}
                                        value={department.value}
                                    >
                                        {department.label}
                                    </option>
                                ))}
                            </NativeSelect>
                        </FilterField>
                        <FilterField label="Status">
                            <NativeSelect
                                value={filters.status ?? ''}
                                onChange={(event) =>
                                    apply({
                                        status: event.target.value || null,
                                    })
                                }
                                className="h-9 w-40"
                            >
                                <option value="">Any status</option>
                                {options.taskStatuses.map((status) => (
                                    <option
                                        key={status.value}
                                        value={status.value}
                                    >
                                        {status.label}
                                    </option>
                                ))}
                            </NativeSelect>
                        </FilterField>
                    </FilterBar>
                </form>

                {view === 'board' ? (
                    <div className="grid crm-scroll gap-3 overflow-x-auto sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-6">
                        {board.map((column) => (
                            <section
                                key={column.department}
                                className="flex min-w-[16rem] flex-col gap-2 rounded-xl bg-muted/30 p-2.5 ring-1 ring-hairline"
                            >
                                <header className="flex items-center justify-between gap-1 px-1">
                                    <button
                                        type="button"
                                        onClick={() =>
                                            toggleDepartment(column.department)
                                        }
                                        aria-expanded={
                                            !collapsedDepartments[
                                                column.department
                                            ]
                                        }
                                        aria-controls={`department-tasks-${column.department}`}
                                        title={
                                            collapsedDepartments[
                                                column.department
                                            ]
                                                ? `Show ${column.label} work`
                                                : `Hide ${column.label} work`
                                        }
                                        className="group flex min-w-0 items-center gap-1 rounded-md py-0.5 pr-1 text-left outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
                                    >
                                        <ChevronDown
                                            aria-hidden="true"
                                            className={cn(
                                                'size-3.5 shrink-0 text-muted-foreground transition-transform',
                                                collapsedDepartments[
                                                    column.department
                                                ] && '-rotate-90',
                                            )}
                                        />
                                        <StatusLabel tone={column.color}>
                                            {column.label}
                                        </StatusLabel>
                                    </button>
                                    <span className="text-xs text-muted-foreground crm-num">
                                        {column.count}
                                    </span>
                                </header>

                                {collapsedDepartments[column.department] ? (
                                    <p className="px-1 py-1 text-[11px] text-muted-foreground">
                                        {column.count === 0
                                            ? 'Nothing waiting.'
                                            : `${column.count} hidden`}
                                    </p>
                                ) : (
                                    <div
                                        id={`department-tasks-${column.department}`}
                                        className="flex flex-col gap-2"
                                    >
                                        {column.tasks.length === 0 ? (
                                            <p className="px-1 py-6 text-center text-xs text-muted-foreground">
                                                Nothing waiting.
                                            </p>
                                        ) : null}

                                        {column.tasks.map((task) => (
                                            <article
                                                key={task.id}
                                                className="flex flex-col gap-1.5 rounded-lg bg-card px-3 py-2.5 shadow-card ring-1 ring-hairline"
                                            >
                                                <div className="flex items-start justify-between gap-2">
                                                    <p className="text-sm leading-snug font-medium">
                                                        {task.title}
                                                    </p>
                                                    <PriorityBadge
                                                        priority={task.priority}
                                                    />
                                                </div>
                                                <p className="text-[11px] text-muted-foreground">
                                                    {task.reference}
                                                    {task.job
                                                        ? ` · ${task.job.job_number}`
                                                        : task.customer
                                                          ? ` · ${task.customer.name}`
                                                          : ''}
                                                </p>
                                                <p className="line-clamp-2 text-xs text-muted-foreground">
                                                    From{' '}
                                                    {task.from_department.label}
                                                    {task.owner
                                                        ? ` · ${task.owner.name}`
                                                        : ' · unassigned'}
                                                </p>
                                                <div className="mt-0.5 flex items-center justify-between gap-2">
                                                    <span
                                                        className={
                                                            task.is_overdue
                                                                ? 'text-[11px] font-medium text-destructive'
                                                                : 'text-[11px] text-muted-foreground'
                                                        }
                                                    >
                                                        {task.due_on
                                                            ? `Due ${formatDate(task.due_on)}`
                                                            : 'No due date'}
                                                    </span>
                                                    {can.manage &&
                                                    task.status.value !==
                                                        'done' ? (
                                                        <Button
                                                            size="sm"
                                                            variant="ghost"
                                                            className="h-7 px-2"
                                                            onClick={() =>
                                                                setCompleting(
                                                                    task,
                                                                )
                                                            }
                                                        >
                                                            Done
                                                        </Button>
                                                    ) : null}
                                                </div>
                                            </article>
                                        ))}
                                    </div>
                                )}
                            </section>
                        ))}
                    </div>
                ) : (
                    <TableCard>
                        <div className="divide-y divide-hairline">
                            {tasks.length === 0 ? (
                                <EmptyState
                                    title="No tasks match these filters"
                                    description="Try another department, or clear the search."
                                    icon={ClipboardList}
                                />
                            ) : null}
                            {tasks.map((task) => (
                                <div
                                    key={task.id}
                                    className="flex flex-col gap-2 px-4 py-3 sm:flex-row sm:items-center sm:justify-between"
                                >
                                    <div className="min-w-0">
                                        <p className="text-sm font-medium">
                                            {task.title}
                                        </p>
                                        <p className="text-xs text-muted-foreground">
                                            {task.reference} ·{' '}
                                            {task.from_department.label} →{' '}
                                            {task.assigned_department.label}
                                            {task.owner
                                                ? ` · ${task.owner.name}`
                                                : ''}
                                            {task.job
                                                ? ` · ${task.job.job_number}`
                                                : ''}
                                        </p>
                                    </div>
                                    <div className="flex shrink-0 items-center gap-3">
                                        <span
                                            className={
                                                task.is_overdue
                                                    ? 'text-xs font-medium text-destructive'
                                                    : 'text-xs text-muted-foreground'
                                            }
                                        >
                                            {task.due_on
                                                ? formatDate(task.due_on)
                                                : 'No due date'}
                                        </span>
                                        <StatusLabel tone={task.status.color}>
                                            {task.status.label}
                                        </StatusLabel>
                                        {can.manage &&
                                        task.status.value !== 'done' ? (
                                            <Button
                                                size="sm"
                                                variant="ghost"
                                                onClick={() =>
                                                    setCompleting(task)
                                                }
                                            >
                                                Complete
                                            </Button>
                                        ) : null}
                                    </div>
                                </div>
                            ))}
                        </div>
                    </TableCard>
                )}
            </div>

            {can.manage ? (
                <>
                    <TaskDialog
                        open={showCreate}
                        options={options}
                        onClose={() => setShowCreate(false)}
                    />
                    {completing ? (
                        <CompleteDialog
                            task={completing}
                            onClose={() => setCompleting(null)}
                        />
                    ) : null}
                </>
            ) : null}
        </>
    );
}

function TaskDialog({
    open,
    options,
    onClose,
}: {
    open: boolean;
    options: {
        departments: StatusOption[];
        priorities: Option[];
        staff: Array<{ value: number; label: string }>;
        customers: Array<{ value: number; label: string }>;
        jobs: Array<{ value: number; label: string }>;
    };
    onClose: () => void;
}) {
    const form = useForm({
        title: '',
        description: '',
        job_id: '',
        customer_id: '',
        from_department: options.departments[0]?.value ?? 'sales',
        assigned_department: options.departments[1]?.value ?? 'operations',
        owner_id: '',
        priority: 'normal',
        due_on: '',
    });

    const submit = () => {
        form.post(store().url, {
            preserveScroll: true,
            onSuccess: () => {
                form.reset();
                onClose();
            },
        });
    };

    return (
        <Dialog open={open} onOpenChange={(state) => !state && onClose()}>
            <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-xl">
                <DialogHeader>
                    <DialogTitle>Hand work to a department</DialogTitle>
                    <DialogDescription>
                        Say what is needed, which install it is about, and when
                        the asking department expects it back.
                    </DialogDescription>
                </DialogHeader>

                <form
                    onSubmit={(event) => {
                        event.preventDefault();
                        submit();
                    }}
                    className="grid gap-3 sm:grid-cols-2"
                >
                    <Field
                        label="Title"
                        error={form.errors.title}
                        required
                        className="sm:col-span-2"
                    >
                        <Input
                            value={form.data.title}
                            onChange={(event) =>
                                form.setData('title', event.target.value)
                            }
                            required
                        />
                    </Field>
                    <Field
                        label="From"
                        error={form.errors.from_department}
                        required
                    >
                        <NativeSelect
                            value={form.data.from_department}
                            onChange={(event) =>
                                form.setData(
                                    'from_department',
                                    event.target.value,
                                )
                            }
                        >
                            {options.departments.map((department) => (
                                <option
                                    key={department.value}
                                    value={department.value}
                                >
                                    {department.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field
                        label="To"
                        error={form.errors.assigned_department}
                        required
                    >
                        <NativeSelect
                            value={form.data.assigned_department}
                            onChange={(event) =>
                                form.setData(
                                    'assigned_department',
                                    event.target.value,
                                )
                            }
                        >
                            {options.departments.map((department) => (
                                <option
                                    key={department.value}
                                    value={department.value}
                                >
                                    {department.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field label="Job" error={form.errors.job_id}>
                        <NativeSelect
                            value={form.data.job_id}
                            onChange={(event) =>
                                form.setData('job_id', event.target.value)
                            }
                        >
                            <option value="">Not job related</option>
                            {options.jobs.map((job) => (
                                <option key={job.value} value={job.value}>
                                    {job.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field label="Customer" error={form.errors.customer_id}>
                        <NativeSelect
                            value={form.data.customer_id}
                            onChange={(event) =>
                                form.setData('customer_id', event.target.value)
                            }
                        >
                            <option value="">No customer</option>
                            {options.customers.map((customer) => (
                                <option
                                    key={customer.value}
                                    value={customer.value}
                                >
                                    {customer.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field label="Owner" error={form.errors.owner_id}>
                        <NativeSelect
                            value={form.data.owner_id}
                            onChange={(event) =>
                                form.setData('owner_id', event.target.value)
                            }
                        >
                            <option value="">Whoever picks it up</option>
                            {options.staff.map((person) => (
                                <option key={person.value} value={person.value}>
                                    {person.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field label="Priority" error={form.errors.priority}>
                        <NativeSelect
                            value={form.data.priority}
                            onChange={(event) =>
                                form.setData('priority', event.target.value)
                            }
                        >
                            {options.priorities.map((priority) => (
                                <option
                                    key={priority.value}
                                    value={priority.value}
                                >
                                    {priority.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field label="Due" error={form.errors.due_on}>
                        <Input
                            type="date"
                            value={form.data.due_on}
                            onChange={(event) =>
                                form.setData('due_on', event.target.value)
                            }
                        />
                    </Field>
                    <Field
                        label="What is needed"
                        error={form.errors.description}
                        className="sm:col-span-2"
                    >
                        <textarea
                            rows={3}
                            value={form.data.description}
                            onChange={(event) =>
                                form.setData('description', event.target.value)
                            }
                            className="w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50"
                        />
                    </Field>

                    <DialogFooter className="sm:col-span-2">
                        <Button type="button" variant="ghost" onClick={onClose}>
                            Cancel
                        </Button>
                        <Button type="submit" disabled={form.processing}>
                            <Save className="size-4" />
                            Create task
                        </Button>
                    </DialogFooter>
                </form>
            </DialogContent>
        </Dialog>
    );
}

function CompleteDialog({
    task,
    onClose,
}: {
    task: TaskRow;
    onClose: () => void;
}) {
    const form = useForm({
        status: 'done',
        completion_notes: '',
    });

    const submit = () => {
        form.patch(update(task.id).url, {
            preserveScroll: true,
            onSuccess: onClose,
        });
    };

    return (
        <Dialog open onOpenChange={(state) => !state && onClose()}>
            <DialogContent className="sm:max-w-md">
                <DialogHeader>
                    <DialogTitle>Complete {task.reference}</DialogTitle>
                    <DialogDescription>
                        What was done, so {task.from_department.label} knows the
                        request has been met.
                    </DialogDescription>
                </DialogHeader>

                <form
                    onSubmit={(event) => {
                        event.preventDefault();
                        submit();
                    }}
                    className="grid gap-3"
                >
                    <Field
                        label="What was done"
                        error={form.errors.completion_notes}
                        required
                    >
                        <textarea
                            rows={3}
                            value={form.data.completion_notes}
                            onChange={(event) =>
                                form.setData(
                                    'completion_notes',
                                    event.target.value,
                                )
                            }
                            className="w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50"
                            required
                        />
                    </Field>

                    <DialogFooter>
                        <Button type="button" variant="ghost" onClick={onClose}>
                            Cancel
                        </Button>
                        <Button type="submit" disabled={form.processing}>
                            <CheckCircle2 className="size-4" />
                            Mark done
                        </Button>
                    </DialogFooter>
                </form>
            </DialogContent>
        </Dialog>
    );
}
