import React, { useEffect, useState } from "react";
import SurveyInfo from "../SurveyInfo/SurveyInfo.tsx";
import QuestionsList, { Question } from "../QuestionsList/QuestionsList.tsx";
import { ISurvey, updateSurvey } from "../../api/SurveyApi.ts";
import {useOutletContext} from "react-router-dom";
import { addNewQuestion, getListQuestions, updateQuestion, deleteQuestion } from "../../api/QuestionApi.ts";
import styles from "./SurveyPage.module.css";
import SaveButton from "../SaveButton/SaveButton.tsx";
import { addNewAnswerVariant, deleteAnswerVariant, getAnswerVariants, IAnswerVariant, updateAnswerVariant } from "../../api/AnswerVariantsApi.ts";

type ActionType =
    | 'update-survey'
    | 'create-question'
    | 'update-question'
    | 'delete-question'
    | 'create-answer'
    | 'update-answer'
    | 'delete-answer';

interface SurveyActionData {
    id: number;
    title: string;
    description: string;
}

interface QuestionActionData {
    surveyId: number;
    id?: number;
    title: string;
    questionType: 'SingleAnswerQuestion' | 'MultipleAnswerQuestion';
}

interface AnswerActionData {
    surveyId: number;
    questionId: number;
    id?: number;
    text: string;
}

interface Action {
    type: ActionType;
    data: SurveyActionData | QuestionActionData | AnswerActionData;
    tempId?: number;
}

class ActionQueue {
    private actions: Action[] = [];
    private idMap: Record<number, number> = {};

    add(action: Action) {
        this.actions.push(action);
    }

    async execute() {
        for (const action of this.actions) {
            try {
                switch (action.type) {
                    case 'update-survey':
                        await this.handleUpdateSurvey(action.data as SurveyActionData);
                        break;
                    case 'create-question': {
                        const createdQuestion = await this.handleCreateQuestion(action.data as QuestionActionData);
                        if (action.tempId) {
                            this.idMap[action.tempId] = createdQuestion.id;
                        }
                        break;
                    }
                    case 'update-question':
                        await this.handleUpdateQuestion(action.data as QuestionActionData & { id: number });
                        break;
                    case 'delete-question':
                        await this.handleDeleteQuestion(action.data as QuestionActionData & { id: number });
                        break;
                    case 'create-answer': {
                        const answerData = action.data as AnswerActionData;
                        await this.handleCreateAnswer({
                            ...answerData,
                            questionId: this.idMap[answerData.questionId] || answerData.questionId
                        });
                        break;
                    }
                    case 'update-answer': {
                        const updateAnswerData = action.data as AnswerActionData & { id: number };
                        await this.handleUpdateAnswer({
                            ...updateAnswerData,
                            questionId: this.idMap[updateAnswerData.questionId] || updateAnswerData.questionId
                        });
                        break;
                    }
                    case 'delete-answer': {
                        const deleteAnswerData = action.data as AnswerActionData & { id: number };
                        await this.handleDeleteAnswer({
                            ...deleteAnswerData,
                            questionId: this.idMap[deleteAnswerData.questionId] || deleteAnswerData.questionId
                        });
                        break;
                    }
                }
            } catch (error) {
                console.error(`Failed to execute action ${action.type}:`, error);
                throw error;
            }
        }
    }

    private async handleUpdateSurvey(data: SurveyActionData) {
        return await updateSurvey(data.id, {
            title: data.title,
            description: data.description
        });
    }

    private async handleCreateQuestion(data: QuestionActionData) {
        return await addNewQuestion(data.surveyId, {
            title: data.title,
            questionType: data.questionType
        });
    }

    private async handleUpdateQuestion(data: QuestionActionData & { id: number }) {
        return await updateQuestion(data.id, {
            title: data.title,
            questionType: data.questionType
        });
    }

    private async handleDeleteQuestion(data: QuestionActionData & { id: number }) {
        return await deleteQuestion(data.id);
    }

    private async handleCreateAnswer(data: AnswerActionData) {
        return await addNewAnswerVariant(data.surveyId, data.questionId, {
            text: data.text
        });
    }

    private async handleUpdateAnswer(data: AnswerActionData & { id: number }) {
        try {
            const result = await updateAnswerVariant(data.id, {
                text: data.text
            });
            return result;
        } catch (error) {
            console.error(error);
            throw error;
        }

    }

    private async handleDeleteAnswer(data: AnswerActionData & { id: number }) {
        return await deleteAnswerVariant(data.id);
    }
}

export const SurveyPage: React.FC = () => {
    const [questions, setQuestions] = useState<Question[]>([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);

    const [description, setDescription] = useState('');
    const [title, setTitle] = useState('');

    const { survey, setSurvey } = useOutletContext<{
        survey: ISurvey;
        setSurvey: (survey: ISurvey) => void;
    }>();

    useEffect(() => {
        if (!survey.id) {
            console.error('Survey ID is missing');
            return;
        }

        const id = survey.id;
        if (isNaN(id)) {
            console.error('Invalid survey ID');
            return;
        }

        const fetchData = async () => {
            try {
                setLoading(true);
                setSurvey(survey);
                setTitle(survey.title);
                setDescription(survey.description);

                const questionsData = await getListQuestions(id);
                const formattedQuestions = await Promise.all(questionsData.map(async q => {
                    const answerVariants = await getAnswerVariants(id, q.id);
                    return {
                        id: q.id,
                        text: q.title,
                        questionType: q.questionType as 'SingleAnswerQuestion' | 'MultipleAnswerQuestion',
                        answerVariants: answerVariants.map((a: IAnswerVariant) => ({
                            id: a.id,
                            text: a.text
                        }))
                    };
                }));
                setQuestions(formattedQuestions);
            } catch (error) {
                console.error('Ошибка:', error);
                setError('Не удалось загрузить опрос');
            } finally {
                setLoading(false);
            }
        };

        fetchData();
    }, [survey.id]);

    const handleSave = async () => {
        if (!survey.id || !survey) return;

        try {
            setError(null);
            const id = survey.id;
            const actionQueue = new ActionQueue();

            actionQueue.add({
                type: 'update-survey',
                data: { id, title, description } as SurveyActionData
            });

            const serverQuestions = await getListQuestions(id);

            questions.forEach(question => {
                const serverQuestion = serverQuestions.find(q => q.id === question.id);
                if (serverQuestion &&
                    (serverQuestion.title !== question.text ||
                        serverQuestion.questionType !== question.questionType)) {
                    actionQueue.add({
                        type: 'update-question',
                        data: {
                            surveyId: id,
                            id: question.id,
                            title: question.text,
                            questionType: question.questionType // Убедитесь, что передается новый тип
                        } as QuestionActionData & { id: number }
                    });
                }
            });

            questions.forEach(question => {
                question.answerVariants.forEach(answer => {
                    if (!answer.id) {
                        actionQueue.add({
                            type: 'create-answer',
                            data: {
                                surveyId: id,
                                questionId: question.id,
                                text: answer.text
                            } as AnswerActionData
                        });
                    } else {
                        actionQueue.add({
                            type: 'update-answer',
                            data: {
                                surveyId: id,
                                questionId: question.id,
                                id: answer.id,
                                text: answer.text
                            } as AnswerActionData & { id: number }
                        });
                    }
                });
            });

            serverQuestions.forEach(serverQuestion => {
                if (!questions.some(q => q.id === serverQuestion.id)) {
                    actionQueue.add({
                        type: 'delete-question',
                        data: {
                            surveyId: id,
                            id: serverQuestion.id
                        } as QuestionActionData & { id: number }
                    });
                }
            });

            await actionQueue.execute();

            const updatedQuestions = await getListQuestions(id);
            const formattedQuestions = await Promise.all(updatedQuestions.map(async q => {
                const answerVariants = await getAnswerVariants(id, q.id);
                return {
                    id: q.id,
                    text: q.title,
                    questionType: q.questionType as 'SingleAnswerQuestion' | 'MultipleAnswerQuestion',
                    answerVariants: answerVariants.map((a: IAnswerVariant) => ({
                        id: a.id,
                        text: a.text
                    }))
                };
            }));
            setQuestions(formattedQuestions);

        } catch (error) {
            console.error('Ошибка сохранения:', error);
            setError(`Ошибка сохранения: ${error instanceof Error ? error.message : 'Неизвестная ошибка'}`);
        }
    };

    if (loading) return <div>Загрузка...</div>;
    if (!survey) return <div>Опрос не найден</div>;

    return (
        <div className={styles.survey_page}>
            <SurveyInfo
                titleSurvey={title}
                descriptionSurvey={description}
                setDescriptionSurvey={setDescription}
                setTitleSurvey={setTitle}
            />
            <QuestionsList
                questions={questions}
                setQuestions={setQuestions}
                surveyId={survey.id}
            />
            {error && <div className={styles.error}>{error}</div>}
            <SaveButton onClick={handleSave}/>
        </div>
    );
};