import { useForm } from '@inertiajs/react';
import { ArrowRight } from 'lucide-react';
import type { FormEvent } from 'react';
import { useEffect, useMemo, useState } from 'react';
import LeaveRequestController from '@/actions/App/Http/Controllers/Admin/LeaveRequestController';
import InputError from '@/components/input-error';
import { Button } from '@/components/ui/button';
import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import { cn } from '@/lib/utils';

export type EmployeeOption = { id: number; code: string; full_name: string };
export type LeaveTypeOption = {
    id: number;
    name: string;
    code: string;
    deducts_balance: boolean;
};
export type BalanceOption = {
    id: number;
    year: number;
    entitled: number;
    taken: number;
    remaining: number;
    leave_type: {
        id: number;
        name: string;
        code: string;
        deducts_balance: boolean;
    };
};

type Props = {
    employees: EmployeeOption[];
    leaveTypes: LeaveTypeOption[];
    initialBalances?: BalanceOption[];
    defaultEmployeeId?: number | null;
    defaultStartDate?: string | null;
    submitUrl?: string;
    onCancel: () => void;
    onSuccess?: () => void;
};

/**
 * Mirrors App\Support\WorkingDaysCalculator::between() for real-time display
 * only — the server always recomputes this value and ignores anything sent
 * by the client.
 */
function businessDaysBetween(start: string, end: string): number {
    if (!start || !end) {
        return 0;
    }

    const startDate = new Date(start);
    const endDate = new Date(end);

    if (endDate < startDate) {
        return 0;
    }

    let days = 0;
    const cursor = new Date(startDate);

    while (cursor <= endDate) {
        const dayOfWeek = cursor.getDay();

        if (dayOfWeek !== 0 && dayOfWeek !== 6) {
            days++;
        }

        cursor.setDate(cursor.getDate() + 1);
    }

    return days;
}

function formatShort(value: string): string {
    if (!value) {
        return '';
    }

    return new Date(value).toLocaleDateString('fr-FR', {
        weekday: 'short',
        day: 'numeric',
        month: 'short',
    });
}

export function LeaveRequestForm({
    employees,
    leaveTypes,
    initialBalances = [],
    defaultEmployeeId = null,
    defaultStartDate = null,
    submitUrl,
    onCancel,
    onSuccess,
}: Props) {
    const needsEmployeePicker = employees.length > 1;
    const [balances, setBalances] = useState(initialBalances);

    const form = useForm({
        employee_id: String(defaultEmployeeId ?? employees[0]?.id ?? ''),
        leave_type_id: String(leaveTypes[0]?.id ?? ''),
        start_date: defaultStartDate ?? '',
        end_date: defaultStartDate ?? '',
        reason: '',
    });

    const computedDays = useMemo(
        () => businessDaysBetween(form.data.start_date, form.data.end_date),
        [form.data.start_date, form.data.end_date],
    );

    useEffect(() => {
        if (!form.data.employee_id) {
            return;
        }

        fetch(
            `/admin/leave-requests/balances?employee_id=${form.data.employee_id}`,
            { headers: { Accept: 'application/json' } },
        )
            .then((response) => response.json())
            .then((payload: { balances: BalanceOption[] }) => {
                setBalances(payload.balances ?? []);
            })
            .catch(() => setBalances([]));
    }, [form.data.employee_id]);

    const selectedType = useMemo(
        () =>
            leaveTypes.find(
                (type) => String(type.id) === form.data.leave_type_id,
            ),
        [leaveTypes, form.data.leave_type_id],
    );

    const selectedBalance = useMemo(() => {
        const typeId = Number(form.data.leave_type_id);

        return balances.find((balance) => balance.leave_type.id === typeId);
    }, [balances, form.data.leave_type_id]);

    const remainingAfterRequest = selectedBalance
        ? Math.max(0, selectedBalance.remaining - computedDays)
        : null;

    const exceedsBalance =
        selectedBalance !== undefined &&
        selectedType?.deducts_balance &&
        computedDays > selectedBalance.remaining;

    function submit(event: FormEvent) {
        event.preventDefault();

        form.transform((data) => ({
            employee_id: Number(data.employee_id),
            leave_type_id: Number(data.leave_type_id),
            start_date: data.start_date,
            end_date: data.end_date,
            reason: data.reason || null,
        }));
        form.post(submitUrl ?? LeaveRequestController.store.url(), {
            preserveScroll: true,
            onSuccess,
        });
    }

    return (
        <form onSubmit={submit} className="space-y-6">
            <Card className="border-none shadow-none">
                <CardHeader>
                    <CardTitle className="text-base">Type de congé</CardTitle>
                    <CardDescription>
                        Choisissez le motif et la période de votre absence
                    </CardDescription>
                </CardHeader>
                <CardContent className="space-y-6">
                    {needsEmployeePicker && (
                        <div className="space-y-2">
                            <Label className="text-xs font-medium tracking-wide text-muted-foreground uppercase">
                                Collaborateur
                            </Label>
                            <Select
                                value={form.data.employee_id}
                                onValueChange={(value) =>
                                    form.setData('employee_id', value)
                                }
                            >
                                <SelectTrigger className="w-full sm:w-80">
                                    <SelectValue placeholder="Choisir" />
                                </SelectTrigger>
                                <SelectContent>
                                    {employees.map((employee) => (
                                        <SelectItem
                                            key={employee.id}
                                            value={String(employee.id)}
                                        >
                                            {employee.full_name}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                            <InputError message={form.errors.employee_id} />
                        </div>
                    )}

                    <div className="space-y-2">
                        <div className="flex flex-wrap gap-2">
                            {leaveTypes.map((type) => {
                                const balance = balances.find(
                                    (b) => b.leave_type.id === type.id,
                                );
                                const isSelected =
                                    form.data.leave_type_id === String(type.id);

                                return (
                                    <button
                                        key={type.id}
                                        type="button"
                                        onClick={() =>
                                            form.setData(
                                                'leave_type_id',
                                                String(type.id),
                                            )
                                        }
                                        className={cn(
                                            'rounded-full border px-4 py-2 text-sm font-medium transition-colors',
                                            isSelected
                                                ? 'border-foreground bg-foreground text-background'
                                                : 'border-border text-foreground hover:border-foreground/40',
                                        )}
                                    >
                                        {type.name}
                                        {type.deducts_balance && balance && (
                                            <span
                                                className={cn(
                                                    'ml-1.5 tabular-nums',
                                                    isSelected
                                                        ? 'text-background/70'
                                                        : 'text-muted-foreground',
                                                )}
                                            >
                                                {balance.remaining}j
                                            </span>
                                        )}
                                    </button>
                                );
                            })}
                        </div>
                        <InputError message={form.errors.leave_type_id} />
                    </div>

                    {selectedType?.deducts_balance && selectedBalance && (
                        <div className="space-y-1.5 rounded-lg border px-3.5 py-3">
                            <div className="flex items-center justify-between text-sm">
                                <span className="text-muted-foreground">
                                    Solde {selectedBalance.year} ·{' '}
                                    {selectedType.name}
                                </span>
                                <span
                                    className={cn(
                                        'font-medium tabular-nums',
                                        exceedsBalance && 'text-destructive',
                                    )}
                                >
                                    {exceedsBalance
                                        ? 'Solde insuffisant'
                                        : `${remainingAfterRequest}j restants après validation`}
                                </span>
                            </div>
                            <div className="h-1 w-full overflow-hidden rounded-full bg-muted">
                                <div
                                    className={cn(
                                        'h-full transition-all',
                                        exceedsBalance
                                            ? 'bg-destructive'
                                            : 'bg-foreground',
                                    )}
                                    style={{
                                        width: `${Math.min(100, (computedDays / Math.max(selectedBalance.remaining, 1)) * 100)}%`,
                                    }}
                                />
                            </div>
                        </div>
                    )}

                    {selectedType?.deducts_balance && !selectedBalance && (
                        <p className="rounded-lg border border-dashed px-3.5 py-3 text-xs text-muted-foreground">
                            Aucun solde défini pour ce type de congé cette
                            année.
                        </p>
                    )}
                </CardContent>
            </Card>

            <Card className="shadow-none">
                <CardHeader>
                    <CardTitle className="text-base">
                        Informations complémentaires
                    </CardTitle>
                    <CardDescription>
                        Période, motif et pièce jointe
                    </CardDescription>
                </CardHeader>
                <CardContent className="space-y-6">
                    <div className="grid gap-x-6 gap-y-2 sm:grid-cols-[1fr_auto_1fr_140px]">
                        <div className="space-y-1.5">
                            <Label
                                htmlFor="start_date"
                                className="text-xs font-medium tracking-wide text-muted-foreground uppercase"
                            >
                                Du
                            </Label>
                            <Input
                                id="start_date"
                                type="date"
                                value={form.data.start_date}
                                onChange={(e) =>
                                    form.setData('start_date', e.target.value)
                                }
                            />
                            {form.data.start_date && (
                                <p className="pl-0.5 text-xs text-muted-foreground capitalize">
                                    {formatShort(form.data.start_date)}
                                </p>
                            )}
                        </div>

                        <ArrowRight className="mt-8 hidden size-4 shrink-0 text-muted-foreground sm:block" />

                        <div className="space-y-1.5">
                            <Label
                                htmlFor="end_date"
                                className="text-xs font-medium tracking-wide text-muted-foreground uppercase"
                            >
                                Au
                            </Label>
                            <Input
                                id="end_date"
                                type="date"
                                value={form.data.end_date}
                                onChange={(e) =>
                                    form.setData('end_date', e.target.value)
                                }
                            />
                            {form.data.end_date && (
                                <p className="pl-0.5 text-xs text-muted-foreground capitalize">
                                    {formatShort(form.data.end_date)}
                                </p>
                            )}
                        </div>

                        <div className="flex flex-col justify-center rounded-lg bg-muted/60 px-3 py-2">
                            <span className="text-xs text-muted-foreground">
                                Jours ouvrés
                            </span>
                            <span className="text-xl font-semibold tabular-nums">
                                {computedDays || '—'}
                            </span>
                        </div>
                    </div>
                    <InputError message={form.errors.start_date} />
                    <InputError message={form.errors.end_date} />

                    <div className="space-y-2">
                        <Label
                            htmlFor="reason"
                            className="text-xs font-medium tracking-wide text-muted-foreground uppercase"
                        >
                            Motif{' '}
                            <span className="normal-case">(optionnel)</span>
                        </Label>
                        <Textarea
                            id="reason"
                            placeholder="Ajoutez un contexte pour votre manager…"
                            value={form.data.reason}
                            onChange={(e) =>
                                form.setData('reason', e.target.value)
                            }
                            rows={8}
                            className="w-full resize-none"
                        />
                        <InputError message={form.errors.reason} />
                    </div>
                </CardContent>
            </Card>

            <div className="flex items-center gap-3">
                <Button type="submit" disabled={form.processing}>
                    Envoyer la demande
                </Button>
                <Button type="button" variant="secondary" onClick={onCancel}>
                    Annuler
                </Button>
            </div>
        </form>
    );
}
