import ComboBoxInput from '@/Components/ComboBoxInput';
import DateInput from '@/Components/DateInput';
import FormInput from '@/Components/FormInput';
import PrimaryButton from '@/Components/PrimaryButton';
import SelectInput from '@/Components/SelectInput';
import TextInput from '@/Components/TextInput';
import {
    Sheet,
    SheetContent,
    SheetDescription,
    SheetHeader,
    SheetTitle,
    SheetTrigger,
} from '@/Components/ui/sheet';
import { t } from '@/lib/utils';
import RecipientsSelectInput from '@/Pages/Alert/RecipientsSelectInput';
import MultiTimePicker from '@/Pages/DrugPrescription/MultiTimePicker';
import WeekDaysSelect from '@/Pages/DrugPrescription/WeekDaysSelect';
import { DrugPrescriptionRecipient, User } from '@/types';
import { useForm } from '@inertiajs/react';
import axios from 'axios';
import dayjs, { Dayjs } from 'dayjs';
import { Loader2 } from 'lucide-react';
import React, { FormEventHandler, useState } from 'react';

interface DrugPrescriptionCreateFormProps {
    availableTimingTypes: string[];
}

type DrugOption = {
    id: number;
    name: string;
    active_ingredient?: string;
    quantity_per_package?: number;
    package_unit?: string;
};

type AdministrationTiming = {
    type: string;
    times: string[];
    date: Dayjs;
    week_days?: number[];
    interval_value?: number;
    interval_unit?: string;
    duration_days?: number;
};

export default function DrugPrescriptionCreateForm({
    availableTimingTypes,
}: DrugPrescriptionCreateFormProps) {
    const [open, setOpen] = React.useState(false);
    const [availableUsers, setAvailableUsers] = useState<User[]>([]);
    const [availableDrugs, setAvailableDrugs] = useState<DrugOption[]>([]);

    const { data, setData, post, processing, errors, reset, transform } =
        useForm({
            user: null as User | null,
            drug: null as DrugOption | null,
            quantity: null as number | null,

            administration_timing: {
                type: 'recurring',
                week_days: [],
                times: [],
                date: dayjs(),
                interval_value: 1,
                interval_unit: 'days',
                duration_days: 30,
            } as AdministrationTiming,

            administration_recipients: [] as DrugPrescriptionRecipient[],
            restock_recipients: [] as DrugPrescriptionRecipient[],

            reminder_max_sends: null as number | null,
            reminder_interval_value: 60 as number,
            reminder_interval_unit: 'minutes' as string,
        });

    const fieldErrors = errors as Record<string, string | undefined>;

    const submit: FormEventHandler = (e) => {
        e.preventDefault();

        transform(
            (d) =>
                ({
                    user_id: d.user ? d.user.id : null,
                    drug_id: d.drug ? d.drug.id : null,
                    quantity: d.quantity,
                    administration_timing: d.administration_timing,

                    recipients: d.administration_recipients
                        .map((recipient) => ({
                            ...recipient,
                            scope: 'administration',
                        }))
                        .concat(
                            d.restock_recipients.map((recipient) => ({
                                ...recipient,
                                scope: 'restock',
                            })),
                        ),

                    reminder_max_sends: d.reminder_max_sends,
                    reminder_interval_value: d.reminder_max_sends
                        ? d.reminder_interval_value
                        : null,
                    reminder_interval_unit: d.reminder_max_sends
                        ? d.reminder_interval_unit
                        : null,
                }) as unknown as typeof d,
        );

        post(route('drug-prescriptions.create'), {
            onSuccess: () => {
                setOpen(false);
                reset();
            },
        });
    };

    const fetchUsers = async (search: string) => {
        try {
            const response = await axios.get(route('search-users'), {
                params: { search },
            });
            setAvailableUsers(response.data);
        } catch (error) {
            console.error('Error fetching users:', error);
        }
    };

    const fetchDrugs = async (search: string) => {
        try {
            const response = await axios.get(route('search-drugs'), {
                params: { search },
            });
            setAvailableDrugs(response.data);
        } catch (error) {
            console.error('Error fetching drugs:', error);
        }
    };

    const availableTypesOptions = availableTimingTypes.map((type) => ({
        value: type,
        label: t(type),
    }));

    const intervalUnitOptions = [
        { value: 'minutes', label: 'Minuti' },
        { value: 'hours', label: 'Ore' },
        { value: 'days', label: 'Giorni' },
    ];

    const reminderIntervalUnitOptions = [
        { value: 'minutes', label: 'Minuti' },
        { value: 'hours', label: 'Ore' },
        { value: 'days', label: 'Giorni' },
    ];

    const timingType = data.administration_timing.type;
    const isRecurringAdministration = timingType === 'recurring';
    const isUniqueAdministration = timingType === 'unique';
    const isIntervalAdministration = timingType === 'interval';
    const quantityPerPackage = data.drug?.quantity_per_package ?? 0;

    function onTimeChange(times: string[]) {
        setData('administration_timing', {
            ...data.administration_timing,
            times,
        });
    }

    function onWeekDaysChange(days: number[]) {
        setData('administration_timing', {
            ...data.administration_timing,
            week_days: days,
        });
    }

    function onTypeChange(type: string) {
        const current = data.administration_timing;

        const base: AdministrationTiming = {
            type,
            times: current.times ?? [],
            date: current.date ?? dayjs(),
        };

        if (type === 'recurring') {
            setData('administration_timing', {
                ...base,
                week_days: current.week_days ?? [],
            });
            return;
        }

        if (type === 'interval') {
            setData('administration_timing', {
                ...base,
                date: current.date ?? dayjs(),
                interval_value: current.interval_value ?? 1,
                interval_unit: current.interval_unit ?? 'days',
                duration_days: current.duration_days ?? 30,
            });
            return;
        }

        setData('administration_timing', base);
    }

    function onDateChange(date: Date) {
        setData('administration_timing', {
            ...data.administration_timing,
            date: dayjs(date),
        });
    }

    function onIntervalValueChange(e: React.ChangeEvent<HTMLInputElement>) {
        const v = parseInt(e.target.value);
        setData('administration_timing', {
            ...data.administration_timing,
            interval_value: !Number.isNaN(v) && v > 0 ? v : 1,
        });
    }

    function onIntervalUnitChange(unit: string) {
        setData('administration_timing', {
            ...data.administration_timing,
            interval_unit: unit,
        });
    }

    function onDurationDaysChange(e: React.ChangeEvent<HTMLInputElement>) {
        const v = parseInt(e.target.value);
        setData('administration_timing', {
            ...data.administration_timing,
            duration_days: !Number.isNaN(v) && v > 0 ? v : 1,
        });
    }

    function onAdministrationRecipientsChange(
        recipients: DrugPrescriptionRecipient[],
    ) {
        setData(
            'administration_recipients',
            recipients.map((recipient) => {
                if (recipient.reminder_offset === undefined)
                    return { ...recipient, reminder_offset: 30 };
                return recipient;
            }),
        );
    }

    function onRestockRecipientsChange(
        recipients: DrugPrescriptionRecipient[],
    ) {
        const maxValue = quantityPerPackage > 0 ? quantityPerPackage : 1;

        setData(
            'restock_recipients',
            recipients.map((recipient) => {
                const currentValue =
                    recipient.reminder_offset === undefined ||
                    recipient.reminder_offset === null
                        ? 1
                        : recipient.reminder_offset;

                return {
                    ...recipient,
                    reminder_offset: Math.min(
                        Math.max(currentValue, 1),
                        maxValue,
                    ),
                };
            }),
        );
    }

    function onAdministrationReminderOffsetChange(
        recipientId: number | string | undefined,
        e: React.ChangeEvent<HTMLInputElement>,
    ) {
        const value = parseInt(e.target.value);
        const updatedRecipients = data.administration_recipients.map(
            (recipient) => {
                if (recipient.id === recipientId)
                    return { ...recipient, reminder_offset: value };
                return recipient;
            },
        );
        setData('administration_recipients', updatedRecipients);
    }

    function onRestockReminderOffsetChange(
        recipientId: number | string | undefined,
        e: React.ChangeEvent<HTMLInputElement>,
    ) {
        const rawValue = parseInt(e.target.value);
        const maxValue = quantityPerPackage > 0 ? quantityPerPackage : 1;

        let value = Number.isNaN(rawValue) ? 1 : rawValue;

        if (value < 1) value = 1;
        if (value > maxValue) value = maxValue;

        const updatedRecipients = data.restock_recipients.map((recipient) => {
            if (recipient.id === recipientId)
                return { ...recipient, reminder_offset: value };
            return recipient;
        });

        setData('restock_recipients', updatedRecipients);
    }

    const renderSelectedAdministrationRecipient = (
        recipient: DrugPrescriptionRecipient,
    ) => {
        return (
            <div>
                <div>{recipient.label}</div>
                <div className="flex items-center justify-between gap-2 text-sm">
                    <TextInput
                        type="number"
                        className="h-7 w-12 p-2 text-center no-spinner"
                        value={recipient.reminder_offset}
                        onChange={(e) =>
                            onAdministrationReminderOffsetChange(
                                recipient.original_id,
                                e,
                            )
                        }
                    />
                    <span>minuti prima</span>
                </div>
            </div>
        );
    };

    const renderSelectedRestockRecipient = (
        recipient: DrugPrescriptionRecipient,
    ) => {
        return (
            <div>
                <div>{recipient.label}</div>
                <div className="flex items-center justify-between gap-2 text-sm">
                    <span>Quando ne rimangono</span>
                    <TextInput
                        type="number"
                        min={1}
                        max={quantityPerPackage > 0 ? quantityPerPackage : 1}
                        className="h-7 w-12 p-2 text-center no-spinner"
                        value={recipient.reminder_offset}
                        onChange={(e) =>
                            onRestockReminderOffsetChange(
                                recipient.original_id,
                                e,
                            )
                        }
                    />
                    <span>o meno</span>
                </div>
            </div>
        );
    };

    const showTimes =
        !isIntervalAdministration ||
        data.administration_timing.interval_unit === 'days';

    return (
        <Sheet open={open} onOpenChange={setOpen}>
            <SheetTrigger asChild>
                <PrimaryButton>Aggiungi</PrimaryButton>
            </SheetTrigger>

            <SheetContent side="right" className="overflow-auto">
                <SheetHeader>
                    <SheetTitle>Nuovo promemoria</SheetTitle>
                    <SheetDescription>
                        <form onSubmit={submit}>
                            <FormInput
                                label="Utente"
                                id="user_id"
                                className="mt-8 block w-full"
                                error={fieldErrors.user_id}
                            >
                                <ComboBoxInput
                                    value={data.user}
                                    options={availableUsers}
                                    renderOption={(user) =>
                                        `${user.name} ${user.surname}`
                                    }
                                    onChange={(value) => setData('user', value)}
                                    onSearchChange={fetchUsers}
                                />
                            </FormInput>

                            <FormInput
                                label="Farmaco"
                                id="drug_id"
                                className="mt-8 block w-full"
                                error={fieldErrors.drug_id}
                            >
                                <ComboBoxInput
                                    value={data.drug}
                                    options={availableDrugs}
                                    renderOption={(drug) =>
                                        `${drug.name} (${drug.active_ingredient})`
                                    }
                                    onChange={(value) => setData('drug', value)}
                                    onSearchChange={fetchDrugs}
                                />
                            </FormInput>

                            <div className="mt-1 text-sm text-gray-700">
                                Quantità per confezione:{' '}
                                <span className="font-semibold">
                                    {quantityPerPackage}
                                </span>
                            </div>

                            <FormInput
                                label="Quantità"
                                id="quantity"
                                className="my-4 block w-full"
                                error={fieldErrors.quantity}
                            >
                                <TextInput
                                    type="number"
                                    step="0.1"
                                    value={data.quantity ?? ''}
                                    onChange={(e) =>
                                        setData(
                                            'quantity',
                                            parseFloat(e.target.value),
                                        )
                                    }
                                    endIcon={
                                        <span className="text-black">
                                            {data.drug?.package_unit}
                                        </span>
                                    }
                                />
                            </FormInput>

                            <FormInput
                                label="Somministrazione"
                                id="administration_timing.type"
                                className="my-4 block w-full"
                                error={
                                    fieldErrors['administration_timing.type']
                                }
                            >
                                <SelectInput
                                    options={availableTypesOptions}
                                    value={data.administration_timing.type}
                                    onChange={onTypeChange}
                                />
                            </FormInput>

                            {isRecurringAdministration ? (
                                <FormInput
                                    label="Giorni"
                                    id="administration_timing.week_days"
                                    className="my-4 block w-full"
                                    error={
                                        fieldErrors[
                                            'administration_timing.week_days'
                                        ]
                                    }
                                >
                                    <WeekDaysSelect
                                        onChange={onWeekDaysChange}
                                        value={
                                            data.administration_timing.week_days
                                        }
                                    />
                                </FormInput>
                            ) : null}

                            {isUniqueAdministration ? (
                                <FormInput
                                    label="Data"
                                    id="administration_timing.date"
                                    className="my-4 block w-full"
                                    error={
                                        fieldErrors[
                                            'administration_timing.date'
                                        ]
                                    }
                                >
                                    <DateInput
                                        date={dayjs(
                                            data.administration_timing.date,
                                        )}
                                        onSelect={onDateChange}
                                    />
                                </FormInput>
                            ) : null}

                            {isIntervalAdministration ? (
                                <>
                                    <div className="my-4 grid grid-cols-2 items-start gap-4">
                                        <FormInput
                                            label="Ogni"
                                            id="administration_timing.interval_value"
                                            className="w-full"
                                            error={
                                                fieldErrors[
                                                    'administration_timing.interval_value'
                                                ]
                                            }
                                        >
                                            <TextInput
                                                type="number"
                                                value={
                                                    data.administration_timing
                                                        .interval_value ?? 1
                                                }
                                                onChange={onIntervalValueChange}
                                            />
                                        </FormInput>

                                        <FormInput
                                            label="Unità"
                                            id="administration_timing.interval_unit"
                                            className="w-full"
                                            error={
                                                fieldErrors[
                                                    'administration_timing.interval_unit'
                                                ]
                                            }
                                        >
                                            <div className="mt-1">
                                                <SelectInput
                                                    value={
                                                        data
                                                            .administration_timing
                                                            .interval_unit ??
                                                        'days'
                                                    }
                                                    options={
                                                        intervalUnitOptions
                                                    }
                                                    onChange={
                                                        onIntervalUnitChange
                                                    }
                                                />
                                            </div>
                                        </FormInput>
                                    </div>

                                    <FormInput
                                        label="Per"
                                        id="administration_timing.duration_days"
                                        className="my-4 block w-full"
                                        error={
                                            fieldErrors[
                                                'administration_timing.duration_days'
                                            ]
                                        }
                                    >
                                        <TextInput
                                            type="number"
                                            value={
                                                data.administration_timing
                                                    .duration_days ?? 1
                                            }
                                            onChange={onDurationDaysChange}
                                            endIcon={
                                                <span className="text-black">
                                                    giorni
                                                </span>
                                            }
                                        />
                                    </FormInput>
                                </>
                            ) : null}

                            {showTimes ? (
                                <MultiTimePicker
                                    label="Orari"
                                    errors={
                                        fieldErrors[
                                            'administration_timing.times'
                                        ]
                                    }
                                    onChange={onTimeChange}
                                    times={data.administration_timing.times}
                                />
                            ) : null}

                            <div className="mt-8 text-black">
                                <div>
                                    Ripetizione promemoria (se non conferma)
                                </div>

                                <FormInput
                                    label="Numero massimo di invii"
                                    id="reminder_max_sends"
                                    error={fieldErrors.reminder_max_sends}
                                >
                                    <TextInput
                                        type="number"
                                        min={1}
                                        value={data.reminder_max_sends ?? ''}
                                        onChange={(e) =>
                                            setData(
                                                'reminder_max_sends',
                                                e.target.value === ''
                                                    ? null
                                                    : parseInt(e.target.value),
                                            )
                                        }
                                        placeholder="(vuoto = senza ripetizioni)"
                                    />
                                </FormInput>

                                <div className="mt-3 grid grid-cols-2 items-start gap-4">
                                    <FormInput
                                        label="Ogni"
                                        id="reminder_interval_value"
                                        className="w-full"
                                        error={
                                            fieldErrors.reminder_interval_value
                                        }
                                    >
                                        <TextInput
                                            type="number"
                                            min={1}
                                            disabled={!data.reminder_max_sends}
                                            value={data.reminder_interval_value}
                                            onChange={(e) =>
                                                setData(
                                                    'reminder_interval_value',
                                                    parseInt(e.target.value),
                                                )
                                            }
                                        />
                                    </FormInput>

                                    <FormInput
                                        label="Unità"
                                        id="reminder_interval_unit"
                                        className="w-full"
                                        error={
                                            fieldErrors.reminder_interval_unit
                                        }
                                    >
                                        <div className="mt-1">
                                            <SelectInput
                                                value={
                                                    data.reminder_interval_unit
                                                }
                                                options={
                                                    reminderIntervalUnitOptions
                                                }
                                                onChange={(value) =>
                                                    setData(
                                                        'reminder_interval_unit',
                                                        value,
                                                    )
                                                }
                                                disabled={
                                                    !data.reminder_max_sends
                                                }
                                            />
                                        </div>
                                    </FormInput>
                                </div>
                            </div>

                            {data.user ? (
                                <div className="mt-8 block w-full">
                                    <RecipientsSelectInput
                                        selectedRecipients={
                                            data.administration_recipients
                                        }
                                        renderSelected={
                                            renderSelectedAdministrationRecipient
                                        }
                                        errors={fieldErrors.recipients}
                                        user={data.user}
                                        label="Invia promemoria somministrazione a"
                                        onChange={
                                            onAdministrationRecipientsChange
                                        }
                                    />
                                </div>
                            ) : null}

                            {data.user ? (
                                <div className="mt-8 block w-full">
                                    <RecipientsSelectInput
                                        selectedRecipients={
                                            data.restock_recipients
                                        }
                                        renderSelected={
                                            renderSelectedRestockRecipient
                                        }
                                        user={data.user}
                                        label="Invia promemoria riassortimento a"
                                        onChange={onRestockRecipientsChange}
                                    />
                                </div>
                            ) : null}

                            <div className="mt-20 flex items-center justify-end">
                                <PrimaryButton
                                    className="ms-4"
                                    disabled={processing}
                                >
                                    {processing ? (
                                        <Loader2 className="animate-spin" />
                                    ) : null}
                                    {t('Save')}
                                </PrimaryButton>
                            </div>
                        </form>
                    </SheetDescription>
                </SheetHeader>
            </SheetContent>
        </Sheet>
    );
}
