import { useForm } from '@inertiajs/react';
import { useMemo, useState } from 'react';
import { StaffSearchSelect } from '@/components/attendance/staff-search-select';
import { ConfirmActionDialog } from '@/components/confirm-action-dialog';
import { AppDateInput } from '@/components/ui/app-date-input';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import {
    calculateInclusiveDaysBetween,
    formatEmployeeJoiningDateOrDash,
} from '@/lib/dates';
import { cn } from '@/lib/utils';

/**
 * @param {object} props
 * @param {'create'|'edit'} props.mode
 * @param {object} [props.application]
 * @param {Array<{staff_type: string, staff_id: number, label: string}>} props.staffOptions
 * @param {string[]} props.leaveTypes
 * @param {Record<string, string>} props.labels
 * @param {string} props.submitUrl
 * @param {'post'|'put'} props.submitMethod
 * @param {string} props.submitLabel
 * @param {string} props.submittingLabel
 * @param {string} props.confirmTitle
 * @param {string} props.confirmBody
 * @param {string} props.cancelLabel
 * @param {(page?: object) => void} [props.onSuccess]
 */
export function LeaveApplicationForm({
    application,
    staffOptions,
    leaveTypes,
    labels,
    submitUrl,
    submitMethod,
    submitLabel,
    submittingLabel,
    confirmTitle,
    confirmBody,
    cancelLabel,
    onSuccess,
}) {
    const [confirmOpen, setConfirmOpen] = useState(false);
    const initialStaffKey =
        application?.staff_type && application?.staff_id
            ? `${application.staff_type}:${application.staff_id}`
            : '';

    const [staffKey, setStaffKey] = useState(initialStaffKey);

    const form = useForm({
        staff_type: application?.staff_type ?? '',
        staff_id: application?.staff_id ?? '',
        leave_type: application?.leave_type ?? 'sick',
        from_date: application?.from_date ?? '',
        to_date: application?.to_date ?? '',
        reason: application?.reason ?? '',
    });

    const totalDays = useMemo(
        () => calculateInclusiveDaysBetween(form.data.from_date, form.data.to_date),
        [form.data.from_date, form.data.to_date],
    );

    function leaveTypeLabel(type) {
        if (type === 'important') {
            return labels.leaveTypeImportant;
        }

        return labels.leaveTypeSick;
    }

    function submit() {
        const [type, id] = staffKey.split(':');
        form.transform((data) => ({
            ...data,
            staff_type: type,
            staff_id: Number(id),
        }));

        const options = {
            preserveScroll: true,
            onSuccess: (page) => {
                setConfirmOpen(false);
                onSuccess?.(page);
            },
        };

        if (submitMethod === 'put') {
            form.put(submitUrl, options);
        } else {
            form.post(submitUrl, options);
        }
    }

    return (
        <form
            className="space-y-6"
            onSubmit={(e) => {
                e.preventDefault();
                setConfirmOpen(true);
            }}
        >
            <div className="grid gap-4 sm:grid-cols-2">
                <div className="space-y-2 sm:col-span-2">
                    <Label htmlFor="leave-staff">{labels.selectStaff}</Label>
                    <StaffSearchSelect
                        id="leave-staff"
                        value={staffKey}
                        onValueChange={setStaffKey}
                        options={staffOptions}
                        placeholder={labels.selectStaff}
                        searchPlaceholder={labels.searchStaffPlaceholder}
                        emptyLabel={labels.searchStaffEmpty}
                    />
                    {form.errors.staff_id ? (
                        <p className="text-destructive text-sm">{form.errors.staff_id}</p>
                    ) : null}
                </div>

                <div className="space-y-2">
                    <Label htmlFor="leave_type">{labels.colLeaveType}</Label>
                    <Select
                        value={form.data.leave_type}
                        onValueChange={(v) => form.setData('leave_type', v)}
                    >
                        <SelectTrigger id="leave_type">
                            <SelectValue />
                        </SelectTrigger>
                        <SelectContent>
                            {leaveTypes.map((type) => (
                                <SelectItem key={type} value={type}>
                                    {leaveTypeLabel(type)}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>
                    {form.errors.leave_type ? (
                        <p className="text-destructive text-sm">{form.errors.leave_type}</p>
                    ) : null}
                </div>

                <div className="space-y-2">
                    <Label>{labels.colTotalDays}</Label>
                    <p className="text-muted-foreground flex h-9 items-center text-sm">
                        {totalDays != null ? String(totalDays) : '—'}
                    </p>
                </div>

                <div className="space-y-2">
                    <Label htmlFor="from_date">{labels.colFromDate}</Label>
                    <AppDateInput
                        id="from_date"
                        forceJalali
                        value={form.data.from_date}
                        onChange={(value) => form.setData('from_date', value)}
                        hint={labels.dateHint}
                        invalid={Boolean(form.errors.from_date)}
                    />
                    {form.data.from_date ? (
                        <p className="text-muted-foreground text-xs">
                            {formatEmployeeJoiningDateOrDash(form.data.from_date)}
                        </p>
                    ) : null}
                    {form.errors.from_date ? (
                        <p className="text-destructive text-sm">{form.errors.from_date}</p>
                    ) : null}
                </div>

                <div className="space-y-2">
                    <Label htmlFor="to_date">{labels.colToDate}</Label>
                    <AppDateInput
                        id="to_date"
                        forceJalali
                        value={form.data.to_date}
                        onChange={(value) => form.setData('to_date', value)}
                        hint={labels.dateHint}
                        invalid={Boolean(form.errors.to_date)}
                    />
                    {form.data.to_date ? (
                        <p className="text-muted-foreground text-xs">
                            {formatEmployeeJoiningDateOrDash(form.data.to_date)}
                        </p>
                    ) : null}
                    {form.errors.to_date ? (
                        <p className="text-destructive text-sm">{form.errors.to_date}</p>
                    ) : null}
                </div>

                <div className="space-y-2 sm:col-span-2">
                    <Label htmlFor="reason">{labels.colReason}</Label>
                    <textarea
                        id="reason"
                        value={form.data.reason}
                        onChange={(e) => form.setData('reason', e.target.value)}
                        rows={4}
                        placeholder={labels.leaveReasonHint}
                        className={cn(
                            'border-input placeholder:text-muted-foreground flex min-h-[6rem] w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none md:text-sm',
                            'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
                            form.errors.reason && 'border-destructive',
                        )}
                    />
                    {form.errors.reason ? (
                        <p className="text-destructive text-sm">{form.errors.reason}</p>
                    ) : null}
                </div>
            </div>

            <Button
                type="submit"
                disabled={!staffKey || !form.data.from_date || !form.data.to_date || form.processing}
            >
                {form.processing ? submittingLabel : submitLabel}
            </Button>

            <ConfirmActionDialog
                open={confirmOpen}
                onOpenChange={setConfirmOpen}
                title={confirmTitle}
                description={confirmBody}
                confirmLabel={submitLabel}
                cancelLabel={cancelLabel}
                processing={form.processing}
                onConfirm={submit}
            />
        </form>
    );
}
