import { Exercise, FillBlanksExercise, LevelPart, ListeningPart, MatchSentencesExercise, MultipleChoiceExercise, ReadingPart, TrueFalseExercise, WriteBlanksExercise, WritingExercise } from "@/interfaces/exam";
import { ModuleState } from "../types";
import ReorderResult from "./types";

const reorderFillBlanks = (exercise: FillBlanksExercise, startId: number): ReorderResult<FillBlanksExercise> => {
    let idMapping = [...exercise.solutions]
        .sort((a, b) => parseInt(a.id) - parseInt(b.id))
        .reduce((acc, solution, index) => {
            acc[solution.id] = (startId + index).toString();
            return acc;
        }, {} as Record<string, string>);

    let newSolutions = [...exercise.solutions]
        .sort((a, b) => parseInt(a.id) - parseInt(b.id))
        .map((solution, index) => ({
            ...solution,
            id: (startId + index).toString()
        }));

    let newText = exercise.text;
    Object.entries(idMapping).forEach(([oldId, newId]) => {
        const regex = new RegExp(`\\{\\{${oldId}\\}\\}`, 'g');
        newText = newText.replace(regex, `{{${newId}}}`);
    });

    let newWords = exercise.words.map(word => {
        if (typeof word === 'string') {
            return word;
        } else if ('letter' in word && 'word' in word) {
            return word;
        } else if ('options' in word && 'id' in word) {
            return {
                ...word,
                id: idMapping[word.id] || word.id
            };
        }
        return word;
    });

    let newUserSolutions = exercise.userSolutions?.map(solution => ({
        ...solution,
        id: idMapping[solution.id] || solution.id
    }));

    return {
        exercise: {
            ...exercise,
            solutions: newSolutions,
            text: newText,
            words: newWords,
            userSolutions: newUserSolutions
        },
        lastId: startId + newSolutions.length
    };
};

const reorderWriteBlanks = (exercise: WriteBlanksExercise, startId: number): ReorderResult<WriteBlanksExercise> => {
    let oldIds = exercise.solutions.map(s => s.id);
    let newIds = oldIds.map((_, index) => (startId + index).toString());

    let newSolutions = exercise.solutions.map((solution, index) => ({
        ...solution,
        id: newIds[index]
    }));

    let newText = exercise.text;
    oldIds.forEach((oldId, index) => {
        newText = newText.replace(
            `{{${oldId}}}`,
            `{{${newIds[index]}}}`
        );
    });

    let result = {
        exercise: {
            ...exercise,
            solutions: newSolutions,
            text: newText
        },
        lastId: startId + newSolutions.length
    };

    return result;
};

const reorderTrueFalse = (exercise: TrueFalseExercise, startId: number): ReorderResult<TrueFalseExercise> => {
    let newQuestions = [...exercise.questions]
        .sort((a, b) => parseInt(a.id) - parseInt(b.id))
        .map((question, index) => ({
            ...question,
            id: (startId + index).toString()
        }));

    return {
        exercise: {
            ...exercise,
            questions: newQuestions
        },
        lastId: startId + newQuestions.length
    };
};

const reorderMatchSentences = (exercise: MatchSentencesExercise, startId: number): ReorderResult<MatchSentencesExercise> => {
    let newSentences = [...exercise.sentences]
        .sort((a, b) => parseInt(a.id) - parseInt(b.id))
        .map((sentence, index) => ({
            ...sentence,
            id: (startId + index).toString()
        }));

    return {
        exercise: {
            ...exercise,
            sentences: newSentences
        },
        lastId: startId + newSentences.length
    };
};


const reorderMultipleChoice = (exercise: MultipleChoiceExercise, startId: number): ReorderResult<MultipleChoiceExercise> => {
    let newQuestions = [...exercise.questions]
        .sort((a, b) => parseInt(a.id) - parseInt(b.id))
        .map((question, index) => ({
            ...question,
            id: (startId + index).toString()
        }));

    return {
        exercise: {
            ...exercise,
            questions: newQuestions
        },
        lastId: startId + newQuestions.length
    };
};


const reorderSection = (exercises: Exercise[], startId: number): { exercises: Exercise[], lastId: number } => {
    let currentId = startId;
    let reorderedExercises = exercises.map(exercise => {
        let result;

        switch (exercise.type) {
            case 'fillBlanks':
                result = reorderFillBlanks(exercise, currentId);
                currentId = result.lastId;
                return result.exercise;

            case 'writeBlanks':
                result = reorderWriteBlanks(exercise, currentId);
                currentId = result.lastId;
                return result.exercise;

            case 'trueFalse':
                result = reorderTrueFalse(exercise, currentId);
                currentId = result.lastId;
                return result.exercise;

            case 'matchSentences':
                result = reorderMatchSentences(exercise, currentId);
                currentId = result.lastId;
                return result.exercise;

            case 'multipleChoice':
                result = reorderMultipleChoice(exercise, currentId);
                currentId = result.lastId;
                return result.exercise;

            case 'writing':
                exercise = { ...exercise, sectionId: currentId };
                currentId += 1;
                return exercise;
            default:
                return exercise;
        }
    });

    return {
        exercises: reorderedExercises,
        lastId: currentId
    };
};


const reorderModule = (moduleState: ModuleState) => {
    let currentId = 1;
    let reorderedSections = moduleState.sections.map(section => {
        let currentSection = section.state as ReadingPart | ListeningPart | LevelPart;
        let result = reorderSection(currentSection.exercises, currentId);
        currentId = result.lastId;
        return {
            ...section,
            state: {
                ...currentSection,
                exercises: result.exercises
            }
        };
    });

    return {
        ...moduleState,
        sections: reorderedSections
    };
};

export {
    reorderFillBlanks,
    reorderWriteBlanks,
    reorderTrueFalse,
    reorderMatchSentences,
    reorderSection,
    reorderModule,
    reorderMultipleChoice,
};