import issPageValues from '@/router/router-constants/issPage-values';
import navigationScenarios from '@/router/router-constants/navigation-scenarios';
import { useMainStore } from '@/store';

export default {
    methods: {
        hasPartQuestions(partsOrQuestions) {
            return partsOrQuestions?.some((pq) => pq.partQuestions?.length > 0);
        },
        hasGlassLocationWithMultipleParts(partsOrQuestions) {
            return partsOrQuestions?.some((pq) => pq.parts?.length > 1);
        },
        hasChildPartQuestions(partsOrQuestions) {
            return partsOrQuestions?.some((pq) => pq.parts?.some((part) => part?.childPartQuestions?.length > 0));
        },
        hasCapabilityQuestions(partsOrQuestions) {
            return partsOrQuestions?.some((pq) => pq.parts?.some((part) => part?.requiresCapabilityQuestions === true));
        },

        // method to only include keys listed for lineItems.glassParts in
        reducedGlassPartsArray(glassParts) {
            const reducedGlassParts = [];
            glassParts.forEach((glass) => {
                if (Array.isArray(glass.parts) && glass.parts.length === 1) {
                    const singlePart = glass.parts[0];
                    if (singlePart) {
                        reducedGlassParts.push({
                            partNumber: singlePart.partNumber,
                            description: singlePart.description,
                            color: singlePart.color,
                            partType: singlePart.partType,
                            canSafeliteRecalibrate: singlePart.canSafeliteRecalibrate,
                            requiresRecalibration: singlePart.requiresRecalibration,
                            requiresCapabilityQuestions: singlePart.requiresCapabilityQuestions,
                            recalibrationType: singlePart.recalibrationType,
                            childParts: singlePart.childParts,
                            price: singlePart.price
                        });
                    }
                }
            });
            return reducedGlassParts;
        },
        comparePageIndices(currentPage, issPage) {
            const orderedVehicleQuestionPages = [
                issPageValues.PART_QUESTIONS,
                issPageValues.VEHICLE_PARTS,
                issPageValues.MOLDING_QUESTIONS,
                issPageValues.CAPABILITY_QUESTIONS,
                issPageValues.QUOTE,
                issPageValues.COVERAGE_STATEMENT
            ];

            return (
                orderedVehicleQuestionPages.indexOf(currentPage)
                - orderedVehicleQuestionPages.indexOf(issPage)
            );
        },
        currentPageComesBeforePage(currentPage = this.$route.query.issPage, issPage) {
            return this.comparePageIndices(currentPage, issPage) < 0;
        },
        currentPageComesAfterPage(currentPage = this.$route.query.issPage, issPage) {
            return this.comparePageIndices(currentPage, issPage) > 0;
        },
        setupInitialData(glass, index, alreadyAnsweredQuestions, vm) {
            const self = vm ?? this;

            // clear answerData if no questions are already answered
            if (!alreadyAnsweredQuestions) {
                glass.answerData = null;
            }

            alreadyAnsweredQuestions?.forEach((answeredGlass) => {
                // if answeredGlass lacks any of these properties then exit
                if (
                    !answeredGlass.glassLocation
                    || !answeredGlass.glassName
                    || !answeredGlass.answeredQuestions
                    || (!answeredGlass.result && !answeredGlass.partNum)
                ) {
                    return;
                }

                // test if glass parts match
                if (
                    glass.glassLocation === answeredGlass.glassLocation
                    && glass.glassName === answeredGlass.glassName
                ) {
                    let answerString = '';

                    // loop through answeredQuestions for matches
                    answeredGlass.answeredQuestions.forEach((answeredQuestion) => {
                        if (!answeredQuestion.questionNum || !answeredQuestion.selectedAnswerText) {
                            return;
                        }
                        // determine which answer was previously chosen
                        const chosenAns = glass.questions[
                            answeredQuestion.questionNum - 1
                        ].answers.find((a) => (
                            a.answerText.toUpperCase()
                                === answeredQuestion.selectedAnswerText.toUpperCase()
                        ));
                        // set the answerString to use for answerSelected
                        if (chosenAns.nextQuestionSequence) {
                            answerString =
                                `${answeredQuestion.questionNum}|nextQuestion|${chosenAns.nextQuestionSequence}|${chosenAns.answerText}`;
                        } else {
                            answerString = `${answeredQuestion.questionNum}|answer|${chosenAns.answerResult}|${chosenAns.answerText}`;
                        }

                        // mark this question as answered (question-chain will read this)
                        glass.questions[answeredQuestion.questionNum - 1].answerSelected = answerString;
                        // mark this question as suppressed if needed (question-chain uses this)
                        if (answeredQuestion.suppressThisQuestion) {
                            glass.questions[
                                answeredQuestion.questionNum - 1
                            ].suppressThisQuestion = true;
                        }
                    });

                    // remove any disabled dependent answers
                    const answerQuestionNums = new Set(alreadyAnsweredQuestions[alreadyAnsweredQuestions.length - 1].answeredQuestions.map((q) => q.questionNum));
                    glass.questions.forEach((q) => {
                        if (!answerQuestionNums.has(q.questionSequence)) {
                            delete q.answerSelected;
                        }
                    });

                    // advance the currentGlassIndex
                    self.currentGlassIndex = index;

                    const answerResult = answeredGlass.partNum
                        ? answeredGlass.partNum
                        : answeredGlass.result;
                    // the above logic for answerResult covers all 3 ___-questions page scenarios

                    // add answerData to current glass
                    glass.answerData = {
                        answerResult,
                        answeredQuestions: answeredGlass.answeredQuestions
                    };
                }
            });

            return glass;
        },
        handleAnswerUpdates(answer, glassKey, vm) {
            // only runs when all questions in a question-chain have been answered
            //      when selectedAnswers updates, user has completed this part's question chain and has a final answer
            //      (does not get run for each invididual question's answer, only when
            //      all relevant questions for the current part have been answered)

            /* answer example format:
                {
                    "answerResult": "DD11132",
                    "answeredQuestions": [
                        {
                            "questionText": "Is your Grand Cherokee the Laredo model?",
                            "selectedAnswerText": "Yes",
                            "questionNum": 1,
                        }
                    ],
                    "index": 0
                }
                */

            const self = vm ?? this;

            // clear out any preloaded answers
            self.selectedAnswers = {};

            // loop through every answered question on the currently answered glass part
            answer.answeredQuestions?.forEach((answeredQuestion) => {
                /* answeredQuestion example format:
                    {
                        "questionText": "Is your Grand Cherokee the Laredo model?",
                        "selectedAnswerText": "Yes",
                        "questionNum": 1,
                    }
                */

                const answeredQuestionText = answeredQuestion.questionText.toUpperCase();
                const answeredQuestionAnswer = answeredQuestion.selectedAnswerText.toUpperCase();

                // HANDLE DUPLICATE QUESTIONS

                // loop through all glass data
                self.questionsData.forEach((glass, glassIndex) => {
                    /* glass example format:
                        {
                            "glassName": "Single",
                            "glassLocation": "Windshield",
                            "parts": null,
                            "questions": [
                                {
                                    "questionSequence": 1,
                                    "questionText": "Is your vehicle equipped with a black dotted pattern behind the rear view mirror, known as a third visor frit?",
                                    "answers": [
                                        {
                                            "answerResult": "DW01537",
                                            "answerText": "Yes",
                                            "nextQuestionSequence": null
                                        },
                                        {
                                            "answerResult": "DW01537b",
                                            "answerText": "No",
                                            "nextQuestionSequence": null
                                        }
                                    ]
                                }
                            ],
                            "answerKey": "Windshield-Single",
                            "answerData": null
                        }
                    */

                    // limit duplicate search to glass pieces that follow after the currently being answered glass piece
                    if (glassIndex > answer.index) {
                        let indexToSuppressTo;
                        // reset this glass piece, in case user is changing their previous answers
                        glass.answerData = null;
                        glass.isSuppressedPart = null;

                        // loop through this glass piece's questions, looking for a questionText match
                        glass.questions.forEach((question, questionIndex) => {
                            // clear out any previously set answers
                            question.answerSelected = null;

                            // clear or set suppressThisQuestion property for each question
                            if (indexToSuppressTo && questionIndex + 1 < indexToSuppressTo) {
                                question.suppressThisQuestion = true;
                            } else {
                                question.suppressThisQuestion = null;
                            }

                            // handle duplicate questions
                            if (question.questionText.toUpperCase() === answeredQuestionText) {
                                let matchedAnswer;

                                // handle matching answer in duplicated question
                                question.answers.forEach((ans) => {
                                    if (ans.answerText.toUpperCase() === answeredQuestionAnswer) {
                                        matchedAnswer = ans;
                                        ans.selected = true;
                                    } else {
                                        ans.selected = null;
                                    }
                                });

                                // handle duplicate's nextQuestion logic on other related questions
                                if (matchedAnswer.nextQuestionSequence) {
                                    // clear any suppression on the nextQuestion
                                    glass.questions[
                                        matchedAnswer.nextQuestionSequence - 1
                                    ].suppressThisQuestion = null;
                                    // if the duplicate is 1ST question in array, set indexToSuppressTo
                                    if (questionIndex === 0) {
                                        if (
                                            !indexToSuppressTo
                                            || matchedAnswer.nextQuestionSequence < indexToSuppressTo
                                        ) {
                                            indexToSuppressTo = matchedAnswer.nextQuestionSequence;
                                        }
                                    }
                                }

                                // update answers in this glass piece's questions with duplication logic modifications
                                glass.questions.forEach((q) => {
                                    q.answers.forEach((a) => {
                                        // revert any previously set nextQuestion logic modifications
                                        if (
                                            a.originalNextQuestionSequence
                                            === question.questionSequence
                                        ) {
                                            // restore original nextQuestionSequence
                                            a.nextQuestionSequence = a.originalNextQuestionSequence;
                                            self.originalNextQuestionSequence = null;
                                            // restore original answerResult
                                            if (a.originalAnswerResult) {
                                                a.answerResult = a.originalAnswerResult;
                                                a.originalAnswerResult = null;
                                            }
                                        }
                                        // modify logic on any related questions
                                        if (a.nextQuestionSequence === question.questionSequence) {
                                            // update either nextQuestionSequence or answerResult

                                            // update questions that lead to duplicated question
                                            if (matchedAnswer.nextQuestionSequence) {
                                                a.originalNextQuestionSequence = a.nextQuestionSequence;
                                                a.nextQuestionSequence = matchedAnswer.nextQuestionSequence;
                                            } else {
                                                a.originalNextQuestionSequence = a.nextQuestionSequence;
                                                a.nextQuestionSequence = null;
                                                a.originalAnswerResult = a.originalAnswerResult || a.answerResult;
                                                a.answerResult = matchedAnswer.answerResult;
                                            }
                                        }
                                    });
                                });

                                // suppress current question
                                question.suppressThisQuestion = true;

                                // are there any questions left that are not suppressed?
                                const remainingQuestions = glass.questions.filter((q) => !q.suppressThisQuestion);

                                if (remainingQuestions.length < 1) {
                                    // this is the final answer for this glass piece

                                    // mark this glass piece as completely answered by adding answerData
                                    const answeredQuestionObj = {
                                        questionText: question.questionText,
                                        selectedAnswerText: matchedAnswer.answerText,
                                        questionNum: question.questionSequence,
                                        suppressThisQuestion: question.suppressThisQuestion
                                    };
                                    // set the answerData (used as indicator that it has been already answered)
                                    glass.answerData = {
                                        answerResult: matchedAnswer.nextQuestionSequence
                                            ? matchedAnswer.nextQuestionSequence
                                            : matchedAnswer.answerResult,
                                        answeredQuestions: [answeredQuestionObj]
                                    };

                                    // suppress this glass piece because it has an answer
                                    glass.isSuppressedPart = true;
                                }
                            }
                        });

                        // Update key to force re-render of glass piece with duplicate question in case user changes previous related answer in the chain
                        self.questionsData[glassIndex].key += Date.now().toString();
                    }
                });
            });

            // set final answer data for the current answered glass part
            self.questionsData[answer.index].answerData = {
                answerResult: answer.answerResult,
                answeredQuestions: answer.answeredQuestions
            };

            // this part has been fully answered, so advance to next part's question chain
            for (let i = answer.index + 1; i < this.questionsData.length; i++) {
                // if this part has not yet been fully answered, then make it the current part
                if (!this.questionsData[i].answerData?.answerResult) {
                    this.currentGlassIndex = i;
                    break;
                }
            }
        },

        async getPartsOrQuestions() {
            try {
                return await useMainStore().getPartsOrQuestions();
            } catch (responseError) {
                return {
                    error: {
                        status: responseError.status,
                        data: responseError.data
                    }
                };
            }
        },

        // Can't use `this` because navigateForward is also called from vin-pages-mixin
        async navigateForward(partsOrQuestions, vm) {
            const self = vm ?? this;
            const currentPage = self.$route.query.issPage;

            const hasPartQuestions = this.hasPartQuestions(partsOrQuestions);
            const hasGlassLocationWithMultipleParts = this.hasGlassLocationWithMultipleParts(partsOrQuestions);
            const hasChildPartQuestions = this.hasChildPartQuestions(partsOrQuestions);
            const hasCapabilityQuestions = this.hasCapabilityQuestions(partsOrQuestions);

            if (hasPartQuestions && this.currentPageComesBeforePage(currentPage, issPageValues.PART_QUESTIONS)) {
                self.$router.navigate(self.navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS, self.$route, {}, {}, { partsOrQuestions });
            } else if (hasGlassLocationWithMultipleParts && this.currentPageComesBeforePage(currentPage, issPageValues.VEHICLE_PARTS)) {
                // if multiple parts on any glass
                // go to vehicle-parts page and pass the partsData
                self.$router.navigate(
                    self.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
                    self.$route,
                    {},
                    {},
                    { partsOrQuestions }
                );
            } else if (
                hasChildPartQuestions
                && this.currentPageComesBeforePage(currentPage, issPageValues.MOLDING_QUESTIONS)
            ) {
                // if any childpart questions
                // go to molding-questions page and pass the partsData
                self.$router.navigate(
                    self.navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
                    self.$route,
                    {},
                    {},
                    { partsOrQuestions }
                );
            } else if (
                hasCapabilityQuestions
                && this.currentPageComesBeforePage(currentPage, issPageValues.CAPABILITY_QUESTIONS)
            ) {
                // if has capability questions
                // go to capability-questions page and pass the partsData

                // mimic part-questions page data for consistency
                // eslint-disable-next-line no-restricted-syntax
                for (const partOrQuestion of partsOrQuestions) {
                    if (this.hasCapabilityQuestions([partOrQuestion])) {
                        const capabilityQuestionsForGlassLocation =
                            (await useMainStore()
                                .getCapabilityQuestions(useMainStore().vehicle.carId, partOrQuestion.parts[0].partNumber)).data;

                        capabilityQuestionsForGlassLocation.forEach((question) => {
                            question.answers = question.answers.map((answer) => ({
                                ...answer,
                                answerResult: answer.answerResult1
                            }));
                        });

                        partOrQuestion.capabilityQuestions = capabilityQuestionsForGlassLocation;
                    }
                }

                self.$router.navigate(
                    self.navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
                    self.$route,
                    {},
                    {},
                    { partsOrQuestions }
                );
            } else {
                // if single parts only
                const collectedGlassParts = this.reducedGlassPartsArray(partsOrQuestions);

                // save to store lineItems.glassParts
                useMainStore().updateGlassParts(collectedGlassParts);

                self.$router.navigate(self.navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS, self.$route);
            }
        },

        navigateBackByVehicleQuestions(vm) {
            const self = vm ?? this;
            const partsOrQuestions = (
                self.mainStore.pageData(issPageValues.CAPABILITY_QUESTIONS)
                ?? self.mainStore.pageData(issPageValues.MOLDING_QUESTIONS)
                ?? self.mainStore.pageData(issPageValues.VEHICLE_PARTS)
                ?? self.mainStore.pageData(issPageValues.PART_QUESTIONS)
            )?.partsOrQuestions;
            const hasPartQuestions = this.hasPartQuestions(partsOrQuestions);
            const hasGlassLocationWithMultipleParts = this.hasGlassLocationWithMultipleParts(partsOrQuestions);
            const hasChildPartQuestions = this.hasChildPartQuestions(partsOrQuestions);
            const hasCapabilityQuestions = this.hasCapabilityQuestions(partsOrQuestions);
            let backNavigationScenario = '';
            if (self.mainStore.order.damage.isRepair) {
                backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_REPAIR;
            } else {
                backNavigationScenario = self.mainStore.vehicle.vin
                    ? navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS
                    : navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS;
            }

            const currentPage = self.$route.query.issPage;
            if (
                hasCapabilityQuestions
                && this.currentPageComesAfterPage(currentPage, issPageValues.CAPABILITY_QUESTIONS)
            ) {
                backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS;
            } else if (
                hasChildPartQuestions
                && this.currentPageComesAfterPage(currentPage, issPageValues.MOLDING_QUESTIONS)
            ) {
                backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS;
            } else if (
                hasGlassLocationWithMultipleParts
                && this.currentPageComesAfterPage(currentPage, issPageValues.VEHICLE_PARTS)
            ) {
                backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE;
            } else if (
                hasPartQuestions
                && this.currentPageComesAfterPage(currentPage, issPageValues.PART_QUESTIONS)
            ) {
                backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS;
            }

            self.$router.navigateWithSpinner(backNavigationScenario, self.$route);
        }
    }
};
