import ComboBoxInput from '@/Components/ComboBoxInput';
import DateInput from '@/Components/DateInput';
import FormInput from '@/Components/FormInput';
import SelectInput from '@/Components/SelectInput';
import SidebarForm from '@/Components/SidebarForm';
import TextInput from '@/Components/TextInput';
import { t } from '@/lib/utils';
import RecipientsSelectInput from '@/Pages/Alert/RecipientsSelectInput';
import MultiTimePicker from '@/Pages/DrugPrescription/MultiTimePicker';
import WeekDaysSelect from '@/Pages/DrugPrescription/WeekDaysSelect';
import {
    DrugPrescription,
    DrugPrescriptionRecipient,
    SidebarFormBodyProps,
} from '@/types';
import axios from 'axios';
import dayjs from 'dayjs';
import React, { useState } from 'react';

interface DrugPrescriptionEditFormProps {
    drugPrescription: DrugPrescription;
    children: React.ReactNode;
    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?: string | Date;
    week_days?: number[];
    interval_value?: number;
    interval_unit?: string;
    duration_days?: number;
};

type DrugPrescriptionFormData = {
    drug: DrugOption | null;
    quantity: number | null;
    administration_timing: AdministrationTiming;
    administration_recipients: DrugPrescriptionRecipient[];
    restock_recipients: DrugPrescriptionRecipient[];
    reminder_max_sends: number | null;
    reminder_interval_value: number;
    reminder_interval_unit: string;
};

export default function DrugPrescriptionEditForm({
    drugPrescription,
    children: trigger,
    availableTimingTypes,
}: DrugPrescriptionEditFormProps) {
    const [availableDrugs, setAvailableDrugs] = useState<DrugOption[]>([]);

    const initialData = {
        drug: drugPrescription.drug,
        quantity: drugPrescription.quantity,
        administration_timing: {
            interval_value: 1,
            interval_unit: 'days',
            duration_days: 30,
            ...drugPrescription.administration_timing,
        },
        administration_recipients: drugPrescription.recipients.filter(
            (recipient) => recipient.scope === 'administration',
        ),
        restock_recipients: drugPrescription.recipients.filter(
            (recipient) => recipient.scope === 'restock',
        ),

        reminder_max_sends: drugPrescription.reminder_max_sends ?? null,
        reminder_interval_value: drugPrescription.reminder_interval_value ?? 60,
        reminder_interval_unit:
            drugPrescription.reminder_interval_unit ?? 'minutes',
    };

    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 Body = (
        bodyProps: Partial<SidebarFormBodyProps<DrugPrescriptionFormData>>,
    ) => {
        const { data, setData, errors, transform } =
            bodyProps as SidebarFormBodyProps<DrugPrescriptionFormData>;

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

        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 items:', error);
            }
        };

        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().toISOString(),
            };

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

            if (type === 'interval') {
                setData('administration_timing', {
                    ...base,
                    date: current.date ?? dayjs().toISOString(),
                    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,
            });
        }

        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 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 value = parseInt(e.target.value);
            const updatedRecipients = data.restock_recipients.map(
                (recipient) => {
                    if (recipient.id === recipientId)
                        return { ...recipient, reminder_offset: value };
                    return recipient;
                },
            );
            setData('restock_recipients', updatedRecipients);
        }

        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[],
        ) {
            setData(
                'restock_recipients',
                recipients.map((recipient) => {
                    if (recipient.reminder_offset === undefined)
                        return { ...recipient, reminder_offset: 1 };
                    return recipient;
                }),
            );
        }

        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
                                    ? recipient.reminder_offset
                                    : 30
                            }
                            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"
                            className="h-7 w-12 p-2 text-center no-spinner"
                            value={
                                recipient.reminder_offset
                                    ? recipient.reminder_offset
                                    : 1
                            }
                            onChange={(e) =>
                                onRestockReminderOffsetChange(
                                    recipient.original_id,
                                    e,
                                )
                            }
                        />
                        <span>o meno</span>
                    </div>
                </div>
            );
        };

        transform((d) => ({
            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,
        }));

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

        return (
            <>
                <FormInput
                    label="Utente"
                    id="user_id"
                    className="mt-8 block w-full"
                >
                    <TextInput
                        value={`${drugPrescription.user.name} ${drugPrescription.user.surname}`}
                        disabled
                    />
                </FormInput>

                <FormInput
                    label="Farmaco"
                    id="drug_id"
                    className="mt-8 block w-full"
                    error={errors.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>

                <div className="mt-2 text-sm text-gray-700">
                    Dosi disponibili:{' '}
                    <span className="font-semibold">{availableDoses}</span>
                </div>

                <FormInput
                    label="Quantità"
                    id="quantity"
                    className="my-4 block w-full"
                    error={errors.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={errors['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={errors['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={errors['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={
                                    errors[
                                        '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={
                                    errors[
                                        '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={
                                errors['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={errors['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={errors.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={errors.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={errors.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>

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

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

    return (
        <SidebarForm
            title="Modifica promemoria"
            trigger={trigger}
            submitMethod={'put'}
            submitRoute={route('admin-drug-prescriptions.update', {
                drugPrescription: drugPrescription.id,
            })}
            initialData={initialData}
        >
            <Body />
        </SidebarForm>
    );
}
