import CitySelectInput from '@/Components/CitySelectInput';
import CompanySelectInput from '@/Components/CompanySelectInput';
import DateInput from '@/Components/DateInput';
import FormInput from '@/Components/FormInput';
import NotificationChannelsSelect from '@/Components/NotificationChannelsSelect';
import PrimaryButton from '@/Components/PrimaryButton';
import SelectInput from '@/Components/SelectInput';
import TextInput from '@/Components/TextInput';
import {
    AccordionContent,
    AccordionItem,
    AccordionTrigger,
} from '@/Components/ui/accordion';
import {
    Sheet,
    SheetContent,
    SheetDescription,
    SheetHeader,
    SheetTitle,
    SheetTrigger,
} from '@/Components/ui/sheet';
import { Textarea } from '@/Components/ui/textarea';
import { t } from '@/lib/utils';
import DevicesSelectInput from '@/Pages/User/DevicesSelectInput';
import DiseasesSelectInput from '@/Pages/User/DiseasesSelectInput';
import OperatorsSelectInput from '@/Pages/User/OperatorsSelectInput';
import { City, Company, Device, Disease, Role, User } from '@/types';
import { useForm } from '@inertiajs/react';
import { Accordion } from '@radix-ui/react-accordion';
import dayjs from 'dayjs';
import { Loader2 } from 'lucide-react';
import React, { FormEventHandler } from 'react';

interface UserCreateFormProps {
    availableRoles: Role[];
    onUserCreated: () => void;
    availableDevices: Device[];
    operatorRole: Role;
    availableGenders: string[];
    availableMaritalStatuses: string[];
    availableBloodTypes: string[];
    availableIdentityDocumentTypes: string[];
    availableBodyTypes: string[];
    availableNotificationChannels: string[];
}

interface UserFormData {
    name: string;
    surname: string;
    email: string;
    role_id: number | null;
    devices: Device[];
    medical_operators: User[];
    birth_city: City | null;
    birth_date: string | Date | null;
    marital_status: string | null;
    phone: string | null;
    residential_city: City | null;
    residential_address: string | null;
    gender: string | null;
    specialization: string | null;
    tax_code: string | null;
    diseases: Disease[];
    blood_type: string | null;
    allergies: string | null;
    surgeries: string | null;
    therapies: string | null;
    notes: string | null;
    identity_document_type: string | null;
    identity_document_number: string | null;
    identity_document_released_at: string | Date | null;
    identity_document_released_by: string | null;
    identity_document_expires_at: string | Date | null;
    height: number | null;
    weight: number | null;
    bmi: number | null;
    body_type: string | null;
    normal_temperature: number | null;
    normal_oxygen_saturation: number | null;
    normal_heart_rate: number | null;
    normal_blood_systolic_pressure: number | null;
    normal_blood_diastolic_pressure: number | null;
    notification_channels: string[];
    company: Company | null;
}

export default function UserCreateForm({
    availableRoles,
    onUserCreated,
    availableDevices,
    operatorRole,
    availableGenders,
    availableMaritalStatuses,
    availableBloodTypes,
    availableIdentityDocumentTypes,
    availableBodyTypes,
    availableNotificationChannels,
}: UserCreateFormProps) {
    const [open, setOpen] = React.useState(false);

    const { data, setData, post, processing, errors, reset, transform } =
        useForm<UserFormData>({
            name: '',
            surname: '',
            email: '',
            role_id: null,
            devices: [],
            medical_operators: [],
            birth_city: null,
            birth_date: null,
            marital_status: null,
            phone: null,
            residential_city: null,
            residential_address: null,
            gender: null,
            specialization: null,
            tax_code: null,
            diseases: [],
            blood_type: null,
            allergies: null,
            surgeries: null,
            therapies: null,
            notes: null,
            identity_document_type: null,
            identity_document_number: null,
            identity_document_released_at: null,
            identity_document_released_by: null,
            identity_document_expires_at: null,
            height: null,
            weight: null,
            bmi: null,
            body_type: null,
            normal_temperature: null,
            normal_oxygen_saturation: null,
            normal_heart_rate: null,
            normal_blood_systolic_pressure: null,
            normal_blood_diastolic_pressure: null,
            notification_channels: ['mail'],
            company: null,
        });
    const formErrors = errors as Record<string, string>;

    const availableRolesOptions = availableRoles.map((role) => ({
        value: role.id,
        label: t(role.name),
    }));

    const availableGendersOptions = availableGenders.map((gender) => ({
        value: gender,
        label: t(gender),
    }));
    const availableBloodTypesOptions = availableBloodTypes.map((type) => ({
        value: type,
        label: t(type),
    }));
    const availableBodyTypesOptions = availableBodyTypes.map((type) => ({
        value: type,
        label: t(type),
    }));
    const availableIdentityDocumentTypesOptions =
        availableIdentityDocumentTypes.map((type) => ({
            value: type,
            label: t(type),
        }));

    const availableMaritalStatusesOptions = availableMaritalStatuses.map(
        (status) => ({
            value: status,
            label: t(status),
        }),
    );

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

        transform(
            (data) =>
                ({
                    ...data,
                    devices: data.devices.map((device) => device.id),
                    medical_operators: data.medical_operators.map(
                        (operator) => operator.id,
                    ),
                    birth_city: data.birth_city ? data.birth_city.id : null,
                    residential_city: data.residential_city
                        ? data.residential_city.id
                        : null,
                    company_id: data.company ? data.company.id : null,
                    diseases: data.diseases.map((disease) => disease.id),
                    identity_document: data.identity_document_type
                        ? {
                              type: data.identity_document_type,
                              number: data.identity_document_number,
                              released_at: data.identity_document_released_at,
                              released_by: data.identity_document_released_by,
                              expires_at: data.identity_document_expires_at,
                          }
                        : null,
                }) as unknown as UserFormData,
        );

        post(route('admin-users.create'), {
            onSuccess: () => {
                setOpen(false);
                onUserCreated();
                reset();
            },
        });
    };

    const selectedRoleIs = (roleName: string) => {
        const targetRole = availableRoles.find(
            (role) => role.name === roleName,
        );
        return targetRole ? data.role_id === targetRole.id : null;
    };

    const selectedRoleIsPatient = selectedRoleIs('user');

    const getDevicesErrors = () => {
        const devicesErrors: Record<number, string> = {};
        for (let i = 0; i < data.devices.length; i++) {
            devicesErrors[i] = formErrors[`devices.${i}`];
        }
        return devicesErrors;
    };

    return (
        <Sheet open={open} onOpenChange={setOpen}>
            <SheetTrigger asChild>
                <PrimaryButton>Aggiungi</PrimaryButton>
            </SheetTrigger>
            <SheetContent side="right" className="overflow-auto">
                <SheetHeader>
                    <SheetTitle>Nuovo utente</SheetTitle>
                    <SheetDescription>
                        <form onSubmit={submit}>
                            <FormInput
                                label={t('name')}
                                id="name"
                                className="mt-8 block w-full"
                                error={errors.name}
                            >
                                <TextInput
                                    isFocused={true}
                                    value={data.name}
                                    onChange={(e) =>
                                        setData('name', e.target.value)
                                    }
                                />
                            </FormInput>
                            <FormInput
                                label={t('surname')}
                                id="surname"
                                className="my-4 block w-full"
                                error={errors.surname}
                            >
                                <TextInput
                                    value={data.surname}
                                    onChange={(e) =>
                                        setData('surname', e.target.value)
                                    }
                                />
                            </FormInput>
                            <FormInput
                                label={t('role')}
                                id="role"
                                className="my-4 block w-full"
                                error={errors.role_id}
                            >
                                <SelectInput
                                    options={availableRolesOptions}
                                    value={data.role_id}
                                    onChange={(value) =>
                                        setData('role_id', parseInt(value))
                                    }
                                />
                            </FormInput>

                            <FormInput
                                label={t('email')}
                                id="email"
                                className="my-4 block w-full"
                                error={errors.email}
                            >
                                <TextInput
                                    value={data.email}
                                    onChange={(e) =>
                                        setData('email', e.target.value)
                                    }
                                />
                            </FormInput>
                            <FormInput
                                label="Numero di telefono"
                                id="phone"
                                className="my-4 block w-full"
                                error={errors.phone}
                            >
                                <TextInput
                                    value={data.phone}
                                    onChange={(e) =>
                                        setData('phone', e.target.value)
                                    }
                                />
                            </FormInput>
                            <FormInput
                                label="Notifica via"
                                id="notification_channels"
                                className="my-4 block w-full"
                                error={errors.notification_channels}
                            >
                                <NotificationChannelsSelect
                                    onChange={(channels) =>
                                        setData(
                                            'notification_channels',
                                            channels,
                                        )
                                    }
                                    value={data.notification_channels}
                                    availableValues={
                                        availableNotificationChannels
                                    }
                                />
                            </FormInput>

                            <FormInput
                                label="Azienda"
                                id="company"
                                className="my-4 block w-full"
                                error={formErrors.company_id}
                            >
                                <CompanySelectInput
                                    value={data.company}
                                    onChange={(company) =>
                                        setData('company', company)
                                    }
                                />
                            </FormInput>

                            {selectedRoleIsPatient ? (
                                <DevicesSelectInput
                                    availableDevices={availableDevices}
                                    selectedDevices={data.devices}
                                    onChange={(devices) =>
                                        setData('devices', devices)
                                    }
                                    errors={getDevicesErrors()}
                                />
                            ) : null}
                            {selectedRoleIsPatient ? (
                                <OperatorsSelectInput
                                    selectedOperators={data.medical_operators}
                                    onChange={(operators) =>
                                        setData('medical_operators', operators)
                                    }
                                    operatorRole={operatorRole}
                                />
                            ) : null}
                            <Accordion
                                type="single"
                                collapsible
                                className="my-4 block w-full"
                            >
                                <AccordionItem value="item-1">
                                    <AccordionTrigger>
                                        Altri dati
                                    </AccordionTrigger>
                                    <AccordionContent className="px-2 text-black">
                                        <FormInput
                                            label="Codice fiscale"
                                            id="tax_code"
                                            className="my-4 block w-full"
                                            error={errors.tax_code}
                                        >
                                            <TextInput
                                                value={data.tax_code}
                                                onChange={(e) =>
                                                    setData(
                                                        'tax_code',
                                                        e.target.value,
                                                    )
                                                }
                                            />
                                        </FormInput>
                                        <FormInput
                                            label="Data di nascita"
                                            id="birth_date"
                                            className="my-4 block w-full"
                                            error={errors.birth_date}
                                        >
                                            <DateInput
                                                date={
                                                    data.birth_date
                                                        ? dayjs(data.birth_date)
                                                        : null
                                                }
                                                onSelect={(date) =>
                                                    setData('birth_date', date)
                                                }
                                            />
                                        </FormInput>
                                        <FormInput
                                            label="Luogo di nascita"
                                            id="birth_city"
                                            className="my-4 block w-full"
                                            error={errors.birth_city}
                                        >
                                            <CitySelectInput
                                                value={data.birth_city}
                                                onChange={(city) =>
                                                    setData('birth_city', city)
                                                }
                                            />
                                        </FormInput>
                                        <FormInput
                                            label="Indirizzo di residenza"
                                            id="residential_address"
                                            className="my-4 block w-full"
                                            error={errors.residential_address}
                                        >
                                            <TextInput
                                                value={data.residential_address}
                                                onChange={(e) =>
                                                    setData(
                                                        'residential_address',
                                                        e.target.value,
                                                    )
                                                }
                                            />
                                        </FormInput>
                                        <FormInput
                                            label="Città di residenza"
                                            id="residential_city"
                                            className="my-4 block w-full"
                                            error={errors.residential_city}
                                        >
                                            <CitySelectInput
                                                value={data.residential_city}
                                                onChange={(city) =>
                                                    setData(
                                                        'residential_city',
                                                        city,
                                                    )
                                                }
                                            />
                                        </FormInput>
                                        <FormInput
                                            label="Genere"
                                            id="gender"
                                            className="my-4 block w-full"
                                            error={errors.gender}
                                        >
                                            <SelectInput
                                                options={
                                                    availableGendersOptions
                                                }
                                                value={data.gender}
                                                onChange={(value) =>
                                                    setData('gender', value)
                                                }
                                            />
                                        </FormInput>
                                        <FormInput
                                            label="Stato civile"
                                            id="marital_status"
                                            className="my-4 block w-full"
                                            error={errors.marital_status}
                                        >
                                            <SelectInput
                                                options={
                                                    availableMaritalStatusesOptions
                                                }
                                                value={data.marital_status}
                                                onChange={(value) =>
                                                    setData(
                                                        'marital_status',
                                                        value,
                                                    )
                                                }
                                            />
                                        </FormInput>
                                        <FormInput
                                            label="Note"
                                            id="notes"
                                            className="mt-8 block w-full"
                                            error={errors.notes}
                                        >
                                            <Textarea
                                                value={data.notes}
                                                onChange={(e) =>
                                                    setData(
                                                        'notes',
                                                        e.target.value,
                                                    )
                                                }
                                            />
                                        </FormInput>
                                    </AccordionContent>
                                </AccordionItem>
                            </Accordion>
                            <Accordion
                                type="single"
                                collapsible
                                className="my-4 block w-full"
                            >
                                <AccordionItem value="item-1">
                                    <AccordionTrigger>
                                        Documento d'identità
                                    </AccordionTrigger>
                                    <AccordionContent className="px-2 text-black">
                                        <FormInput
                                            label="Tipo"
                                            id="identity_document_number_type"
                                            className="my-4 block w-full"
                                            error={
                                                errors.identity_document_type
                                            }
                                        >
                                            <SelectInput
                                                options={
                                                    availableIdentityDocumentTypesOptions
                                                }
                                                value={
                                                    data.identity_document_type
                                                }
                                                onChange={(value) =>
                                                    setData(
                                                        'identity_document_type',
                                                        value,
                                                    )
                                                }
                                            />
                                        </FormInput>
                                        <FormInput
                                            label="Numero"
                                            id="identity_document_number"
                                            className="my-4 block w-full"
                                            error={
                                                errors.identity_document_number
                                            }
                                        >
                                            <TextInput
                                                value={
                                                    data.identity_document_number
                                                }
                                                onChange={(e) =>
                                                    setData(
                                                        'identity_document_number',
                                                        e.target.value,
                                                    )
                                                }
                                            />
                                        </FormInput>
                                        <FormInput
                                            label="Rilasciato da"
                                            id="identity_document_released_by"
                                            className="my-4 block w-full"
                                            error={
                                                errors.identity_document_released_by
                                            }
                                        >
                                            <TextInput
                                                value={
                                                    data.identity_document_released_by
                                                }
                                                onChange={(e) =>
                                                    setData(
                                                        'identity_document_released_by',
                                                        e.target.value,
                                                    )
                                                }
                                            />
                                        </FormInput>
                                        <FormInput
                                            label="Data di rilascio"
                                            id="identity_document_released_at"
                                            className="my-4 block w-full"
                                            error={errors.birth_date}
                                        >
                                            <DateInput
                                                disabledFuture
                                                date={
                                                    data.identity_document_released_at
                                                        ? dayjs(
                                                              data.identity_document_released_at,
                                                          )
                                                        : null
                                                }
                                                onSelect={(date) =>
                                                    setData(
                                                        'identity_document_released_at',
                                                        date,
                                                    )
                                                }
                                            />
                                        </FormInput>
                                        <FormInput
                                            label="Data di scadenza"
                                            id="identity_document_expires_at"
                                            className="my-4 block w-full"
                                            error={
                                                errors.identity_document_expires_at
                                            }
                                        >
                                            <DateInput
                                                disabledPast
                                                date={
                                                    data.identity_document_expires_at
                                                        ? dayjs(
                                                              data.identity_document_expires_at,
                                                          )
                                                        : null
                                                }
                                                onSelect={(date) =>
                                                    setData(
                                                        'identity_document_expires_at',
                                                        date,
                                                    )
                                                }
                                            />
                                        </FormInput>
                                    </AccordionContent>
                                </AccordionItem>
                            </Accordion>

                            {selectedRoleIsPatient ? (
                                <Accordion
                                    type="single"
                                    collapsible
                                    className="my-4 block w-full"
                                >
                                    <AccordionItem value="item-1">
                                        <AccordionTrigger>
                                            Dati sanitari
                                        </AccordionTrigger>
                                        <AccordionContent className="px-2 text-black">
                                            <FormInput
                                                label="Gruppo sanguigno"
                                                id="blood_type"
                                                className="my-4 block w-full"
                                                error={errors.blood_type}
                                            >
                                                <SelectInput
                                                    options={
                                                        availableBloodTypesOptions
                                                    }
                                                    value={data.blood_type}
                                                    onChange={(value) =>
                                                        setData(
                                                            'blood_type',
                                                            value,
                                                        )
                                                    }
                                                />
                                            </FormInput>
                                            <FormInput
                                                label="Allergie"
                                                id="allergies"
                                                className="mt-8 block w-full"
                                                error={errors.allergies}
                                            >
                                                <Textarea
                                                    value={data.allergies}
                                                    onChange={(e) =>
                                                        setData(
                                                            'allergies',
                                                            e.target.value,
                                                        )
                                                    }
                                                />
                                            </FormInput>
                                            <FormInput
                                                label="Interventi chirurgici passati"
                                                id="surgeries"
                                                className="mt-8 block w-full"
                                                error={errors.surgeries}
                                            >
                                                <Textarea
                                                    value={data.surgeries}
                                                    onChange={(e) =>
                                                        setData(
                                                            'surgeries',
                                                            e.target.value,
                                                        )
                                                    }
                                                />
                                            </FormInput>
                                            <FormInput
                                                label="Terapie in corso"
                                                id="therapies"
                                                className="mt-8 block w-full"
                                                error={errors.therapies}
                                            >
                                                <Textarea
                                                    value={data.therapies}
                                                    onChange={(e) =>
                                                        setData(
                                                            'therapies',
                                                            e.target.value,
                                                        )
                                                    }
                                                />
                                            </FormInput>
                                            <DiseasesSelectInput
                                                selectedDiseases={data.diseases}
                                                onChange={(diseases) =>
                                                    setData(
                                                        'diseases',
                                                        diseases,
                                                    )
                                                }
                                            />
                                        </AccordionContent>
                                    </AccordionItem>
                                </Accordion>
                            ) : null}

                            {selectedRoleIsPatient ? (
                                <Accordion
                                    type="single"
                                    collapsible
                                    className="my-4 block w-full"
                                >
                                    <AccordionItem value="item-1">
                                        <AccordionTrigger>
                                            Dati biometrici
                                        </AccordionTrigger>
                                        <AccordionContent className="px-2 text-black">
                                            <FormInput
                                                label="Altezza"
                                                id="height"
                                                className="my-4 block w-full"
                                                error={errors.height}
                                            >
                                                <TextInput
                                                    type="number"
                                                    value={data.height}
                                                    onChange={(e) =>
                                                        setData(
                                                            'height',
                                                            parseInt(
                                                                e.target.value,
                                                            ),
                                                        )
                                                    }
                                                    endIcon="cm"
                                                />
                                            </FormInput>
                                            <FormInput
                                                label="Peso"
                                                id="weight"
                                                className="my-4 block w-full"
                                                error={errors.weight}
                                            >
                                                <TextInput
                                                    type="number"
                                                    value={data.weight}
                                                    onChange={(e) =>
                                                        setData(
                                                            'weight',
                                                            parseInt(
                                                                e.target.value,
                                                            ),
                                                        )
                                                    }
                                                    endIcon="kg"
                                                />
                                            </FormInput>
                                            <FormInput
                                                label="BMI"
                                                id="bmi"
                                                className="my-4 block w-full"
                                                error={errors.bmi}
                                            >
                                                <TextInput
                                                    type="number"
                                                    step="0.1"
                                                    value={data.bmi}
                                                    onChange={(e) =>
                                                        setData(
                                                            'bmi',
                                                            parseFloat(
                                                                e.target.value,
                                                            ),
                                                        )
                                                    }
                                                />
                                            </FormInput>
                                            <FormInput
                                                label="Corporatura"
                                                id="body_type"
                                                className="my-4 block w-full"
                                                error={errors.body_type}
                                            >
                                                <SelectInput
                                                    options={
                                                        availableBodyTypesOptions
                                                    }
                                                    value={data.body_type}
                                                    onChange={(value) =>
                                                        setData(
                                                            'body_type',
                                                            value,
                                                        )
                                                    }
                                                />
                                            </FormInput>
                                        </AccordionContent>
                                    </AccordionItem>
                                </Accordion>
                            ) : null}

                            {selectedRoleIsPatient ? (
                                <Accordion
                                    type="single"
                                    collapsible
                                    className="my-4 block w-full"
                                >
                                    <AccordionItem value="item-1">
                                        <AccordionTrigger>
                                            Parametri vitali base
                                        </AccordionTrigger>
                                        <AccordionContent className="px-2 text-black">
                                            <FormInput
                                                label="Pressione sistolica"
                                                id="normal_blood_systolic_pressure"
                                                className="my-4 block w-full"
                                                error={
                                                    errors.normal_blood_systolic_pressure
                                                }
                                            >
                                                <TextInput
                                                    type="number"
                                                    value={
                                                        data.normal_blood_systolic_pressure
                                                    }
                                                    onChange={(e) =>
                                                        setData(
                                                            'normal_blood_systolic_pressure',
                                                            parseInt(
                                                                e.target.value,
                                                            ),
                                                        )
                                                    }
                                                    endIcon="mmHg"
                                                />
                                            </FormInput>
                                            <FormInput
                                                label="Pressione diastolica"
                                                id="normal_blood_diastolic_pressure"
                                                className="my-4 block w-full"
                                                error={
                                                    errors.normal_blood_diastolic_pressure
                                                }
                                            >
                                                <TextInput
                                                    type="number"
                                                    value={
                                                        data.normal_blood_diastolic_pressure
                                                    }
                                                    onChange={(e) =>
                                                        setData(
                                                            'normal_blood_diastolic_pressure',
                                                            parseInt(
                                                                e.target.value,
                                                            ),
                                                        )
                                                    }
                                                    endIcon="mmHg"
                                                />
                                            </FormInput>
                                            <FormInput
                                                label="Frequenza cardiaca"
                                                id="normal_heart_rate"
                                                className="my-4 block w-full"
                                                error={errors.normal_heart_rate}
                                            >
                                                <TextInput
                                                    type="number"
                                                    value={
                                                        data.normal_heart_rate
                                                    }
                                                    onChange={(e) =>
                                                        setData(
                                                            'normal_heart_rate',
                                                            parseInt(
                                                                e.target.value,
                                                            ),
                                                        )
                                                    }
                                                    endIcon="bpm"
                                                />
                                            </FormInput>
                                            <FormInput
                                                label="Saturazione d'ossigeno"
                                                id="normal_oxygen_saturation"
                                                className="my-4 block w-full"
                                                error={
                                                    errors.normal_oxygen_saturation
                                                }
                                            >
                                                <TextInput
                                                    type="number"
                                                    value={
                                                        data.normal_oxygen_saturation
                                                    }
                                                    onChange={(e) =>
                                                        setData(
                                                            'normal_oxygen_saturation',
                                                            parseInt(
                                                                e.target.value,
                                                            ),
                                                        )
                                                    }
                                                    endIcon="%"
                                                />
                                            </FormInput>
                                            <FormInput
                                                label="Temperatura"
                                                id="normal_temperature"
                                                className="my-4 block w-full"
                                                error={
                                                    errors.normal_temperature
                                                }
                                            >
                                                <TextInput
                                                    type="number"
                                                    step="0.1"
                                                    value={
                                                        data.normal_temperature
                                                    }
                                                    onChange={(e) =>
                                                        setData(
                                                            'normal_temperature',
                                                            parseFloat(
                                                                e.target.value,
                                                            ),
                                                        )
                                                    }
                                                    endIcon="°C"
                                                />
                                            </FormInput>
                                        </AccordionContent>
                                    </AccordionItem>
                                </Accordion>
                            ) : 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>
    );
}
