import {Form, notification} from "antd";
import {useDispatch, useSelector} from "react-redux";
import {closeModal, setSelectedScheduledAppointment} from "../../../Redux/Slices/appointmentsSlice.js";
import {useEffect, useMemo, useRef, useState} from "react";
import dayjs from "dayjs";
import {useGetAppointmentsQuery} from "../../../Api/appointmentsApi.js";
import {Grid} from "antd";
import {useUploadAppointmentFileMutation} from "../../../Api/appointmentFilesApi.js";

const {useBreakpoint} = Grid;

const useAppointmentFormModalUI = (createAppointment, patients, cancelAppointment, useGetByPatientIdQuery) => {
    const dispatch = useDispatch();

    const {userData} = useSelector((state) => state.auth);
    const {modalVisible, scheduledData} = useSelector((state) => state.appointmentsUI);
    const [form] = Form.useForm();
    const screens = useBreakpoint();

    const [selectedPatient, setSelectedPatient] = useState(null);
    const [currentStep, setCurrentStep] = useState(0);
    const [appointmentDate, setAppointmentDate] = useState(dayjs(new Date()));
    const [searchPatientString, setSearchPatientString] = useState("");
    const [formValues, setFormValues] = useState({});
    const [isDrawerVisible, setIsDrawerVisible] = useState(false);
    const [searchPreviousAppointments, setSearchPreviousAppointments] = useState("");
    const [draftFiles, setDraftFiles] = useState([]);
    const editorRef = useRef(null);

    const [uploadAppointmentFile, {isLoading: isUploadingFile}] = useUploadAppointmentFileMutation();

    const startDate = appointmentDate.startOf('month').utc().format('YYYY-MM-DD');
    const endDate = appointmentDate.endOf('month').utc().format('YYYY-MM-DD');

    const {
        data: appointments = [],
        isLoading: isLoadingAppointments,
        isError: isErrorAppointments,
    } = useGetAppointmentsQuery(
        {doctor_id: userData.id, start_date: startDate, end_date: endDate},
        {
            pollingInterval: 60000,
            skip: !userData.id,
        }
    );

    const {
        data: previousAppointments = [],
        isLoading: isLoadingPreviousAppointments,
        isError: isErrorPreviousAppointments,
    } = useGetByPatientIdQuery(selectedPatient?.id, {
        pollingInterval: 20000,
        skip: !selectedPatient,
    });

    useEffect(() => {
        if (isErrorAppointments) {
            notification.error({
                message: 'Ошибка',
                description: 'Ошибка загрузки приемов.',
                placement: 'topRight',
            });
        }
    }, [isErrorAppointments]);

    const blockStepStyle = {marginBottom: 16};
    const searchInputStyle = {marginBottom: 16};
    const chooseContainerStyle = {maxHeight: 400, overflowY: "auto"};
    const loadingContainerStyle = {display: "flex", justifyContent: "center", alignItems: "center", height: 200};
    const stepsContentStyle = {marginBottom: 16};
    const stepsIndicatorStyle = {marginBottom: 16};
    const footerRowStyle = {marginTop: 16};
    const footerButtonStyle = {marginRight: 8};

    const screenXS = !screens.sm;
    const direction = screenXS ? "vertical" : "horizontal";

    const joditConfig = useMemo(
        () => ({
            readonly: false,
            height: 150,
            toolbarAdaptive: false,
            buttons: [
                "bold", "italic", "underline", "strikethrough", "|",
                "superscript", "subscript", "|",
                "ul", "ol", "outdent", "indent", "|",
                "font", "fontsize", "brush", "paragraph", "|",
                "align", "hr", "|",
                "table", "link", "image", "video", "symbols", "|",
                "undo", "redo", "cut", "copy", "paste", "selectall", "eraser", "|",
                "find", "source", "fullsize", "print", "preview",
            ],
            autofocus: false,
            preserveSelection: true,
            askBeforePasteHTML: false,
            askBeforePasteFromWord: false,
            defaultActionOnPaste: "insert_clear_html",
            spellcheck: true,
            placeholder: "Введите результаты приёма...",
            showCharsCounter: true,
            showWordsCounter: true,
            showXPathInStatusbar: false,
            toolbarSticky: true,
            toolbarButtonSize: "middle",
            cleanHTML: {
                removeEmptyElements: true,
                replaceNBSP: false,
            },
            hotkeys: {
                "ctrl + shift + f": "find",
                "ctrl + b": "bold",
                "ctrl + i": "italic",
                "ctrl + u": "underline",
            },
            image: {
                editSrc: true,
                editTitle: true,
                editAlt: true,
                openOnDblClick: false,
            },
            video: {
                allowedSources: ["youtube", "vimeo"],
            },
            uploader: {
                insertImageAsBase64URI: true,
            },
            paste: {
                insertAsBase64: true,
                mimeTypes: ["image/png", "image/jpeg", "image/gif"],
                maxFileSize: 5 * 1024 * 1024, // 5MB
                error: () => {
                    notification.error({
                        message: "Ошибка вставки",
                        description: "Файл слишком большой или неподдерживаемый формат.",
                        placement: "topRight",
                    });
                },
            },
        }),
        []
    );

    const filteredPatients = useMemo(
        () =>
            patients.filter((patient) => {
                const searchLower = searchPatientString.toLowerCase();
                return Object.values(patient)
                    .filter((value) => typeof value === "string")
                    .some((value) => value.toLowerCase().includes(searchLower));
            }),
        [patients, searchPatientString]
    );

    const filteredPreviousAppointments = useMemo(
        () =>
            previousAppointments.filter((appointment) => {
                const searchLower = searchPreviousAppointments.toLowerCase();
                return appointment.results?.toLowerCase().includes(searchLower);
            }),
        [previousAppointments, searchPreviousAppointments]
    );

    const handleAddFile = (file) => {
        const maxSize = 10 * 1024 * 1024; // 10MB
        if (file.size > maxSize) {
            notification.error({
                message: "Ошибка вставки",
                description: "Файл слишком большой.",
                placement: "topRight",
            });
            return false;
        }
        setDraftFiles((prev) => [...prev, file]);
        return false;
    };

    const handleRemoveFile = (file) => {
        setDraftFiles((prev) => prev.filter((f) => f.uid !== file.uid));
    };

    useEffect(() => {
        if (modalVisible) {
            form.resetFields();
            setSelectedPatient(null);
            setCurrentStep(0);
            setSearchPatientString("");
            setFormValues({});
            setIsDrawerVisible(false);
            setSearchPreviousAppointments("");
            setDraftFiles([]);

            if (scheduledData) {
                const patient = patients.find((p) => p.id === scheduledData.patient_id);
                if (patient) {
                    setSelectedPatient(patient);
                    setCurrentStep(1);
                    form.setFieldsValue({
                        patient_id: scheduledData.patient_id,
                        type_id: scheduledData.type_id,
                        appointment_datetime: dayjs(scheduledData.appointment_datetime),
                        results: scheduledData.results || "",
                    });
                    setAppointmentDate(dayjs(scheduledData.appointment_datetime));
                }
            } else {
                form.setFieldsValue({
                    appointment_datetime: dayjs(new Date()),
                    results: "",
                });
            }
        }
    }, [modalVisible, form, scheduledData, patients]);

    const handleSetSearchPatientString = (e) => {
        setSearchPatientString(e.target.value);
    };

    const handleSetSearchPreviousAppointments = (e) => {
        setSearchPreviousAppointments(e.target.value);
    };

    const getDateString = (date) => {
        return date ? dayjs(date).format("DD.MM.YYYY") : "Не указано";
    };

    const getSelectedPatientBirthdayString = () => {
        return selectedPatient ? getDateString(selectedPatient.birthday) : "Не выбран";
    };

    const resetPatient = () => {
        setSelectedPatient(null);
        form.setFieldsValue({patient_id: undefined});
    };

    const resetForm = () => {
        form.resetFields();
        setSelectedPatient(null);
        setCurrentStep(0);
        setSearchPatientString("");
        setFormValues({});
        setIsDrawerVisible(false);
        setDraftFiles([]);
        setAppointmentDate(dayjs(new Date())); // Сбрасываем дату
    };

    const handleSetAppointmentDate = (date) => {
        setAppointmentDate(date);
        form.setFieldsValue({appointment_datetime: date}); // Синхронизируем форму
    };

    const modalWidth = useMemo(() => (screenXS ? 700 : "90%"), [screenXS]);

    const showDrawer = () => {
        setIsDrawerVisible(true);
    };

    const closeDrawer = () => {
        setIsDrawerVisible(false);
        setSearchPreviousAppointments("");
    };

    const handleClickNextButton = async () => {
        if (currentStep === 0) {
            if (!selectedPatient) {
                notification.error({
                    message: "Ошибка",
                    description: "Пожалуйста, выберите пациента.",
                    placement: "topRight",
                });
                return;
            }
            form.setFieldsValue({patient_id: selectedPatient.id});
            setCurrentStep(1);
        } else if (currentStep === 1) {
            try {
                const values = await form.validateFields();
                setFormValues(values);
                setCurrentStep(2);
            } catch (error) {
                notification.error({
                    message: "Ошибка валидации",
                    description: error.message || "Пожалуйста, заполните все обязательные поля.",
                    placement: "topRight",
                });
            }
        } else if (currentStep === 2) {
            await handleOk();
        }
    };

    const handleClickBackButton = () => {
        if (currentStep > 0) {
            setCurrentStep(currentStep - 1);
        }
    };

    const handleOk = async () => {
        try {
            const values = formValues;
            const appointmentTime = values.appointment_datetime;
            const hasConflict = appointments.some((app) =>
                dayjs(app.appointment_datetime).isSame(appointmentTime, "minute")
            );

            if (hasConflict) {
                notification.error({
                    message: "Конфликт времени",
                    description: "Выбранное время уже занято другим приемом.",
                    placement: "topRight",
                });
                return;
            }

            const data = {
                patient_id: selectedPatient.id,
                type_id: values.type_id,
                appointment_datetime: appointmentTime.format("YYYY-MM-DD HH:mm:ss"),
                days_until_the_next_appointment: values.days_until_the_next_appointment,
                results: values.results || "",
            };

            const response = await createAppointment(data).unwrap();

            for (const file of draftFiles) {
                try {
                    await uploadAppointmentFile({
                        appointmentId: response.id,
                        file: file,
                    }).unwrap();
                } catch (error) {
                    console.error(`Error uploading file ${file.name}:`, error);
                    const errorMessage = error.data?.detail
                        ? JSON.stringify(error.data.detail, null, 2)
                        : JSON.stringify(error.data || error.message || "Неизвестная ошибка", null, 2);
                    notification.error({
                        message: "Ошибка загрузки файла",
                        description: `Не удалось загрузить файл ${file.name}: ${errorMessage}`,
                        placement: "topRight",
                    });
                }
            }

            if (scheduledData) {
                await cancelScheduledAppointment(scheduledData.id);
                dispatch(setSelectedScheduledAppointment(null));
            }

            notification.success({
                message: "Прием создан",
                description: "Прием успешно создан.",
                placement: "topRight",
            });

            resetForm();
            dispatch(closeModal());
        } catch (error) {
            console.error("Error creating appointment:", error);
            notification.error({
                message: "Ошибка создания приема",
                description: `Не удалось создать прием: ${JSON.stringify(error.data?.detail || error.data || error.message || "Неизвестная ошибка", null, 2)}`,
                placement: "topRight",
            });
        }
    };

    const cancelScheduledAppointment = async (selectedScheduledAppointmentId) => {
        try {
            await cancelAppointment(selectedScheduledAppointmentId);
        } catch (error) {
            console.error("Error cancelling appointment:", error);
            notification.error({
                message: "Ошибка",
                description: error.data?.message || "Не удалось отменить прием.",
                placement: "topRight",
            });
        }
    };

    const handleCancel = () => {
        resetForm();
        dispatch(closeModal());
    };

    const disableBackButton = currentStep === 0;
    const disableNextButton = currentStep === 0 && !selectedPatient;
    const nextButtonText = currentStep === 2 ? "Создать" : "Далее";

    return {
        form,
        modalVisible,
        selectedPatient,
        setSelectedPatient,
        currentStep,
        searchPatientString,
        appointmentDate,
        editor: editorRef,
        handleSetSearchPatientString,
        filteredPatients,
        filteredPreviousAppointments,
        searchPreviousAppointments,
        handleSetSearchPreviousAppointments,
        handleOk,
        handleCancel,
        resetPatient,
        getDateString,
        getSelectedPatientBirthdayString,
        handleClickNextButton,
        handleClickBackButton,
        handleSetAppointmentDate,
        modalWidth,
        disableBackButton,
        disableNextButton,
        nextButtonText,
        blockStepStyle,
        searchInputStyle,
        chooseContainerStyle,
        loadingContainerStyle,
        stepsContentStyle,
        stepsIndicatorStyle,
        footerRowStyle,
        footerButtonStyle,
        screenXS,
        direction,
        isDrawerVisible,
        showDrawer,
        closeDrawer,
        isLoadingPreviousAppointments,
        isErrorPreviousAppointments,
        joditConfig,
        draftFiles,
        handleAddFile,
        handleRemoveFile,
        isUploadingFile,
        isLoadingAppointments,
        isErrorAppointments,
    };
};

export default useAppointmentFormModalUI;