import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
import { setCurrentQuizStep, useQuizViewStore } from "@stores/quizView/store";
import { useCallback, useDebugValue, useMemo, useState } from "react";
import { isResultQuestionEmpty } from "../../pages/ViewPublicationPage/tools/checkEmptyData";
import { useQuizData } from "./useQuizData";
import moment from "moment";


export function useQuestionFlowControl() {
    const { settings, questions } = useQuizData();
    const [currentQuestion, setCurrentQuestion] = useState<AnyTypedQuizQuestion>(getFirstQuestion);
    const { answers, pointsSum } = useQuizViewStore(state => state);


    const linearQuestionIndex = questions.every(({ content }) => content.rule.parentId !== "root") // null when branching enabled
        ? questions.indexOf(currentQuestion)
        : null;

    function getFirstQuestion() {
        if (questions.length === 0) throw new Error("No questions found");

        if (settings.cfg.haveRoot) {
            const nextQuestion = questions.find(
                question => question.id === settings.cfg.haveRoot || question.content.id === settings.cfg.haveRoot
            );
            if (!nextQuestion) throw new Error("Root question not found");

            return nextQuestion;
        }

        return questions[0];
    }


    const nextQuestionIdPointsLogic = () => {
        return questions.find(question =>
            question.type === "result" && question.content.rule.parentId === "line"
        )
    }

    const nextQuestionIdMainLogic = () => {
        const questionAnswer = answers.find(({ questionId }) => questionId === currentQuestion.id);

        //Если ответ существует и не является объектом момента
        if (questionAnswer && !moment.isMoment(questionAnswer.answer)) {
            //Ответы должны храниться в массиве
            const userAnswers = Array.isArray(questionAnswer.answer) ? questionAnswer.answer : [questionAnswer.answer];

            //Сравниваем список условий ветвления и выбираем подходящее
            for (const branchingRule of currentQuestion.content.rule.main) {
                if (userAnswers.some(answer => branchingRule.rules[0].answers.includes(answer))) {
                    return branchingRule.next;
                }
            }
        }

        if (!currentQuestion.required) {//вопрос не обязателен и не нашли совпадений между ответами и условиями ветвления
            const defaultNextQuestionId = currentQuestion.content.rule.default;
            if (defaultNextQuestionId.length > 1 && defaultNextQuestionId !== " ") return defaultNextQuestionId;
            //Вопросы типа страница, ползунок, своё поле для ввода и дата не могут иметь больше 1 ребёнка. Пользователь не может настроить там дефолт
            //Кинуть на ребёнка надо даже если там нет дефолта
            if (
                ["date", "page", "text", "number"].includes(currentQuestion.type)
                && currentQuestion.content.rule.children.length === 1
            ) return currentQuestion.content.rule.children[0];
        }

        //ничё не нашли, ищем резулт 
        return questions.find(q => {
            return q.type === "result" && q.content.rule.parentId === currentQuestion.content.id;
        })?.id;
    };
    const calculateNextQuestionId = useMemo(() => {
        if (Boolean(settings.cfg.score)) {
            return nextQuestionIdPointsLogic()
        }
        return nextQuestionIdMainLogic()
    }, [answers, currentQuestion, questions])

    const prevQuestion = linearQuestionIndex !== null
        ? questions[linearQuestionIndex - 1]
        : questions.find(q =>
            q.id === currentQuestion.content.rule.parentId
            || q.content.id === currentQuestion.content.rule.parentId
        );

    const findResultPointsLogic = () => {
        const results = questions
        .filter(e => e.type === "result" && e.content.rule.minScore !== undefined && e.content.rule.minScore <= pointsSum)
        const numbers = results.map(e => e.content.rule.minScore)
        const indexOfNext = Math.max(...numbers) 
        console.log(results)
        console.log(numbers)
        console.log(indexOfNext)
        return results[numbers.indexOf(indexOfNext)]
    }

    const nextQuestion = () => {
        let next
        //Искать можно двумя логиками. Основной и балловой
        if (Boolean(settings.cfg.score)) {
            //Балловая


            //Ищем линейно
            if (linearQuestionIndex !== null) {


                next = questions[linearQuestionIndex + 1] 
                if (next.type === "result") next = findResultPointsLogic()


            }


        } else {
            //Основная
            if (linearQuestionIndex !== null) {
                //Ищем линейно
                next = questions[linearQuestionIndex + 1] ?? questions.find(question =>
                    question.type === "result" && question.content.rule.parentId === "line"
                )
            } else {
                //Ищем ветвлением
                next = questions.find(q => q.id === calculateNextQuestionId || q.content.id === calculateNextQuestionId);
            }
        }
        if (!next) throw new Error("Не найден следующий вопрос")
        console.log("next", next)
        return next
    }

    const showResult = useCallback(() => {
        if (nextQuestion?.type !== "result") throw new Error("Current question is not result");
        if (isResultQuestionEmpty(nextQuestion)) {
            setCurrentQuizStep("contactform");
            return;
        }

        setCurrentQuestion(nextQuestion);
        if (settings.cfg.resultInfo.showResultForm === "after") setCurrentQuizStep("contactform");
    }, [nextQuestion, settings.cfg.resultInfo.showResultForm]);

    const showResultAfterContactForm = useCallback(() => {
        if (currentQuestion.type !== "result") throw new Error("Current question is not result");
        if (isResultQuestionEmpty(currentQuestion)) {
            console.warn("Result question is empty");
            return;
        }

        setCurrentQuizStep("question");
    }, [currentQuestion]);

    const moveToPrevQuestion = useCallback(() => {
        if (!prevQuestion) throw new Error("Previous question not found");

        setCurrentQuestion(prevQuestion);
    }, [prevQuestion]);

    const moveToNextQuestion = useCallback(() => {
        if (!nextQuestion) throw new Error("Next question not found");

        if (nextQuestion.type === "result") return showResult();

        setCurrentQuestion(nextQuestion);
    }, [nextQuestion, showResult]);

    const isPreviousButtonEnabled = Boolean(prevQuestion);

    const isNextButtonEnabled = useMemo(() => {
        const hasAnswer = answers.some(({ questionId }) => questionId === currentQuestion.id);

        if ("required" in currentQuestion.content && currentQuestion.content.required) {
            return hasAnswer;
        }

        return Boolean(nextQuestion);
    }, [answers, currentQuestion.content, currentQuestion.id, nextQuestion]);

    useDebugValue({
        linearQuestionIndex,
        currentQuestionTitle: currentQuestion.title,
        prevQuestionTitle: prevQuestion?.title,
        nextQuestionTitle: nextQuestion?.title,
    });

    return {
        currentQuestion,
        currentQuestionStepNumber: linearQuestionIndex === null ? null : linearQuestionIndex + 1,
        isNextButtonEnabled,
        isPreviousButtonEnabled,
        moveToPrevQuestion,
        moveToNextQuestion,
        showResultAfterContactForm,
    };
} 
