import JoditEditor from "jodit-react";
import dayjs from "dayjs";
import {
    Button,
    Collapse,
    DatePicker,
    Form,
    Input,
    InputNumber,
    Modal,
    Result,
    Row,
    Select,
    Spin,
    Steps,
    Typography,
    Drawer,
    Upload,
    List,
} from "antd";
import {UploadOutlined} from '@ant-design/icons';
import useAppointmentFormModal from "./useAppointmentFormModal.js";
import useAppointmentFormModalUI from "./useAppointmentFormModalUI.js";
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
import {useMemo, useCallback, useRef} from "react";

const AppointmentFormModal = () => {
    const appointmentFormModalData = useAppointmentFormModal();
    const appointmentFormModalUI = useAppointmentFormModalUI(
        appointmentFormModalData.createAppointment,
        appointmentFormModalData.patients,
        appointmentFormModalData.cancelAppointment,
        appointmentFormModalData.useGetByPatientIdQuery
    );

    const cursorPositionRef = useRef(null);

    const saveCursorPosition = useCallback(() => {
        if (appointmentFormModalUI.editor.current) {
            const editor = appointmentFormModalUI.editor.current.editor;
            const selection = editor.selection;
            if (selection) {
                cursorPositionRef.current = selection.getBookmark();
            }
        }
    }, [appointmentFormModalUI.editor]);

    const restoreCursorPosition = useCallback(() => {
        if (appointmentFormModalUI.editor.current && cursorPositionRef.current) {
            const editor = appointmentFormModalUI.editor.current.editor;
            const selection = editor.selection;
            if (selection && cursorPositionRef.current) {
                selection.moveToBookmark(cursorPositionRef.current);
            }
        }
    }, [appointmentFormModalUI.editor]);

    const handleEditorBlur = useCallback(
        (newContent) => {
            saveCursorPosition();
            appointmentFormModalUI.form.setFieldsValue({results: newContent});
            setTimeout(restoreCursorPosition, 0);
        },
        [appointmentFormModalUI.form, saveCursorPosition, restoreCursorPosition]
    );

    const patientsItems = useMemo(() =>
            appointmentFormModalUI.filteredPatients.map((patient) => ({
                key: patient.id,
                label: `${patient.last_name} ${patient.first_name} (${appointmentFormModalUI.getDateString(patient.birthday)})`,
                children: (
                    <div>
                        <p>
                            <b>Пациент:</b> {patient.last_name} {patient.first_name}
                        </p>
                        <p>
                            <b>Дата рождения:</b> {appointmentFormModalUI.getDateString(patient.birthday)}
                        </p>
                        <p>
                            <b>Диагноз:</b> {patient.diagnosis || "Не указан"}
                        </p>
                        <p>
                            <b>Email:</b> {patient.email || "Не указан"}
                        </p>
                        <p>
                            <b>Телефон:</b> {patient.phone || ""}
                        </p>
                        <Button type="primary" onClick={() => appointmentFormModalUI.setSelectedPatient(patient)}>
                            Выбрать
                        </Button>
                    </div>
                ),
            })),
        [appointmentFormModalUI.filteredPatients, appointmentFormModalUI.getDateString, appointmentFormModalUI.setSelectedPatient]
    );

    const SelectPatientStep = useMemo(() => {
        return appointmentFormModalUI.selectedPatient ? (
            <div style={appointmentFormModalUI.blockStepStyle}>
                <Typography.Text strong>
                    {appointmentFormModalUI.selectedPatient.last_name} {appointmentFormModalUI.selectedPatient.first_name}
                </Typography.Text>
                <p>
                    <b>Дата рождения:</b> {appointmentFormModalUI.getSelectedPatientBirthdayString()}
                </p>
                <p>
                    <b>Email:</b> {appointmentFormModalUI.selectedPatient.email || "Не указан"}
                </p>
                <p>
                    <b>Телефон:</b> {appointmentFormModalUI.selectedPatient.phone || ""}
                </p>
                <Button type="primary" onClick={appointmentFormModalUI.resetPatient} danger>
                    Выбрать другого пациента
                </Button>
            </div>
        ) : (
            <>
                <Input
                    placeholder="Поиск пациента"
                    value={appointmentFormModalUI.searchPatientString}
                    onChange={appointmentFormModalUI.handleSetSearchPatientString}
                    style={appointmentFormModalUI.searchInputStyle}
                    allowClear
                />
                <div style={appointmentFormModalUI.chooseContainerStyle}>
                    <Collapse items={patientsItems}/>
                </div>
            </>
        );
    }, [
        appointmentFormModalUI.selectedPatient,
        appointmentFormModalUI.searchPatientString,
        appointmentFormModalUI.blockStepStyle,
        appointmentFormModalUI.chooseContainerStyle,
        appointmentFormModalUI.searchInputStyle,
        appointmentFormModalUI.getSelectedPatientBirthdayString,
        appointmentFormModalUI.resetPatient,
        appointmentFormModalUI.handleSetSearchPatientString,
        patientsItems,
    ]);

    const AppointmentStep = useMemo(() => {
        return (
            <div>
                <Button
                    type="primary"
                    onClick={appointmentFormModalUI.showDrawer}
                    style={{marginBottom: 16}}
                    disabled={!appointmentFormModalUI.selectedPatient}
                >
                    Показать прошлые приемы
                </Button>
                <Form
                    form={appointmentFormModalUI.form}
                    onFinish={appointmentFormModalUI.handleOk}
                    initialValues={{
                        patient_id: appointmentFormModalUI.selectedPatient?.id,
                    }}
                    layout="vertical"
                >
                    <Form.Item name="type_id" label="Тип приема"
                               rules={[{required: true, message: "Выберите тип приема"}]}>
                        <Select placeholder="Выберите тип приема">
                            {appointmentFormModalData.appointmentTypes.map((type) => (
                                <Select.Option key={type.id} value={type.id}>
                                    {type.title}
                                </Select.Option>
                            ))}
                        </Select>
                    </Form.Item>
                    <Form.Item
                        name="appointment_datetime"
                        label="Время приема"
                        rules={[{required: true, message: "Выберите время"}]}
                    >
                        <DatePicker
                            maxDate={dayjs(new Date()).add(1, "day")}
                            showTime
                            format="DD.MM.YYYY HH:mm"
                            style={{width: "100%"}}
                        />
                    </Form.Item>
                    <Form.Item
                        name="days_until_the_next_appointment"
                        label="Дней до следующего приема"
                        rules={[{type: "number", min: 0, message: "Введите неотрицательное число"}]}
                    >
                        <InputNumber min={0} style={{width: "100%"}}/>
                    </Form.Item>
                    <Form.Item name="results" label="Результаты приема">
                        <div className="jodit-container">
                            <JoditEditor
                                ref={appointmentFormModalUI.editor}
                                value={appointmentFormModalUI.form.getFieldValue("results") || ""}
                                config={appointmentFormModalUI.joditConfig}
                                onBlur={handleEditorBlur}
                            />
                        </div>
                    </Form.Item>
                    <Form.Item name="files" label="Прикрепить файлы">
                        <Upload
                            fileList={appointmentFormModalUI.draftFiles}
                            beforeUpload={(file) => {
                                appointmentFormModalUI.handleAddFile(file);
                                return false; // Prevent auto-upload
                            }}
                            onRemove={(file) => appointmentFormModalUI.handleRemoveFile(file)}
                            accept=".pdf,.doc,.docx,.jpg,.jpeg,.png"
                            multiple
                        >
                            <Button icon={<UploadOutlined/>}>Выбрать файлы</Button>
                        </Upload>
                    </Form.Item>
                </Form>
            </div>
        );
    }, [
        appointmentFormModalUI.form,
        appointmentFormModalUI.selectedPatient,
        appointmentFormModalUI.showDrawer,
        appointmentFormModalUI.editor,
        appointmentFormModalUI.draftFiles,
        appointmentFormModalUI.handleAddFile,
        appointmentFormModalUI.handleRemoveFile,
        appointmentFormModalData.appointmentTypes,
        appointmentFormModalUI.joditConfig,
        handleEditorBlur,
    ]);

    const ConfirmStep = useMemo(() => {
        const values = appointmentFormModalUI.form.getFieldsValue();
        const patient = appointmentFormModalData.patients.find((p) => p.id === values.patient_id);
        const appointmentType = appointmentFormModalData.appointmentTypes.find((t) => t.id === values.type_id);

        return (
            <div style={appointmentFormModalUI.blockStepStyle}>
                <Typography.Title level={4}>Подтверждение</Typography.Title>
                <p>
                    <b>Пациент:</b> {patient ? `${patient.last_name} ${patient.first_name}` : "Не указан"}
                </p>
                <p>
                    <b>Тип приема:</b> {appointmentType ? appointmentType.title : "Не указан"}
                </p>
                <p>
                    <b>Время приема:</b>{" "}
                    {values.appointment_datetime ? dayjs(values.appointment_datetime).format("DD.MM.YYYY HH:mm") : "Не указано"}
                </p>
                <p>
                    <b>Дней до следующего приема:</b> {values.days_until_the_next_appointment || "Не указано"}
                </p>
                <p>
                    <b>Результаты приема:</b>
                </p>
                <div dangerouslySetInnerHTML={{__html: values.results || "Не указаны"}}/>
                <p>
                    <b>Прикрепленные файлы:</b>
                </p>
                {appointmentFormModalUI.draftFiles.length > 0 ? (
                    <List
                        dataSource={appointmentFormModalUI.draftFiles}
                        renderItem={(file) => (
                            <List.Item>
                                {file.name} ({(file.size / 1024 / 1024).toFixed(2)} MB)
                            </List.Item>
                        )}
                    />
                ) : (
                    <p>Файлы не прикреплены</p>
                )}
            </div>
        );
    }, [appointmentFormModalUI.form, appointmentFormModalData.patients, appointmentFormModalData.appointmentTypes, appointmentFormModalUI.draftFiles, appointmentFormModalUI.blockStepStyle]);

    const steps = useMemo(() => [
        {
            title: "Выбор пациента",
            content: SelectPatientStep,
        },
        {
            title: "Заполнение информации о приеме",
            content: AppointmentStep,
        },
        {
            title: "Подтверждение",
            content: ConfirmStep,
        },
    ], [SelectPatientStep, AppointmentStep, ConfirmStep]);

    if (appointmentFormModalData.isError) {
        return (
            <Result
                status="error"
                title="Ошибка"
                subTitle="Произошла ошибка в работе страницы"
            />
        );
    }

    return (
        <>
            {appointmentFormModalData.isLoading ? (
                <LoadingIndicator/>
            ) : (
                <>
                    <Modal
                        title={"Создать прием"}
                        open={appointmentFormModalUI.modalVisible}
                        onCancel={appointmentFormModalUI.handleCancel}
                        footer={null}
                        width={appointmentFormModalUI.modalWidth}
                    >
                        {appointmentFormModalData.isLoading ? (
                            <div style={appointmentFormModalUI.loadingContainerStyle}>
                                <Spin size="large"/>
                            </div>
                        ) : (
                            <div
                                style={appointmentFormModalUI.stepsContentStyle}>{steps[appointmentFormModalUI.currentStep].content}</div>
                        )}

                        {!appointmentFormModalUI.screenXS && (
                            <Steps
                                current={appointmentFormModalUI.currentStep}
                                items={steps}
                                style={appointmentFormModalUI.stepsIndicatorStyle}
                                direction={appointmentFormModalUI.direction}
                            />
                        )}

                        <Row justify="end" style={appointmentFormModalUI.footerRowStyle} gutter={[8, 8]}>
                            <Button
                                style={appointmentFormModalUI.footerButtonStyle}
                                onClick={appointmentFormModalUI.handleClickBackButton}
                                disabled={appointmentFormModalUI.disableBackButton || appointmentFormModalUI.isUploadingFile || appointmentFormModalData.isProcessed}
                            >
                                Назад
                            </Button>
                            <Button
                                type="primary"
                                onClick={appointmentFormModalUI.handleClickNextButton}
                                disabled={appointmentFormModalUI.disableNextButton}
                                loading={appointmentFormModalData.isProcessed || appointmentFormModalUI.isUploadingFile}
                            >
                                {appointmentFormModalUI.nextButtonText}
                            </Button>
                        </Row>
                    </Modal>
                    <Drawer
                        title="Прошлые приемы"
                        placement="right"
                        onClose={appointmentFormModalUI.closeDrawer}
                        open={appointmentFormModalUI.isDrawerVisible}
                        width={400}
                    >
                        <Input
                            placeholder="Поиск по результатам приема"
                            value={appointmentFormModalUI.searchPreviousAppointments}
                            onChange={appointmentFormModalUI.handleSetSearchPreviousAppointments}
                            style={{marginBottom: 16}}
                            allowClear
                        />
                        <Collapse
                            items={appointmentFormModalUI.filteredPreviousAppointments.map((appointment) => ({
                                key: appointment.id,
                                label: `Прием ${dayjs(appointment.appointment_datetime).format("DD.MM.YYYY HH:mm")}`,
                                children: <div
                                    dangerouslySetInnerHTML={{__html: appointment.results || "Результаты не указаны"}}/>,
                            }))}
                        />
                    </Drawer>
                </>
            )}
        </>
    );
};

export default AppointmentFormModal;