import wordstore from "../../../mc/wordStore.json";
import useTranslation from "../../../hooks/useTranslation";

const choiceListAndAnswer = ({
  optionObject = {},
  correctValue = "",
  answerValue = "",
}) => {
  if (typeof optionObject !== "object" || !optionObject) {
    return { options: [], answer: null, isCorrect: false };
  }
  const options = Object.keys(optionObject).map((key) => ({
    id: key,
    text: optionObject?.[key],
    isCorrect: key === correctValue || optionObject[key] === correctValue,
  }));

  const answer =
    options.find(
      (option) => option?.id === answerValue || option?.text === answerValue,
    ) || null;

  const correct =
    options.find(
      (option) => option?.id === correctValue || option?.text === correctValue,
    ) || null;

  return {
    options,
    answer,
    isCorrect: !!(answer && correct && answer?.id === correct?.id),
    correctIndex: options?.findIndex((option) => option?.id === correct?.id),
    correctText: correct?.text,
  };
};

const hasAnswerData = ({ data = null }) => {
  const answer = data?.answer?.data?.session_id;
  return Boolean(answer);
};

function convertToParagraphWithSpans(inputText) {
  let processedText = inputText.replace(/<IMPROVEMENT>/g, "<span>");
  processedText = processedText.replace(/<\/IMPROVEMENT>/g, "</span>");

  return processedText;
}

const quizResponses = ({ responses = [], type = "scripted" }) => {
  if (responses.length === 0 && !responses) {
    return [];
  }
  return responses?.map((response, index) => {
    if (type === "unscripted") {
      return {
        key: index + 1,
        recording: response,
      };
    }
    if (type === "written") {
      return {
        key: index + 1,
        index: index,
        text: response,
      };
    }
    return {
      key: index + 1,
      text: response?.text,
      recording: response?.recording,
    };
  });
};

const getColor = (aiScore) => {
  if (typeof aiScore !== "number") return;
  let color = "";
  if (aiScore <= 27) {
    color = "rgba(249, 84, 84, 1)";
  } else if (aiScore >= 28 && aiScore <= 45) {
    color = "rgba(151, 71, 255, 1)";
  } else if (aiScore >= 46 && aiScore <= 60) {
    color = "rgba(219, 136, 13, 1)";
  } else if (aiScore >= 61 && aiScore <= 74) {
    color = "rgba(229, 173, 14, 1)";
  } else if (aiScore >= 75 && aiScore <= 87) {
    color = "rgba(13, 95, 219, 1)";
  } else if (aiScore >= 88 && aiScore <= 94) {
    color = "rgba(13, 125, 150, 1)";
  } else if (aiScore > 94) {
    color = "rgba(85, 193, 0, 1)";
  } else {
    color = "rgba(249, 84, 84, 1)";
  }

  return color;
};

const dialogueResponses = ({
  responses = [],
  type = "scriped",
  questionListEntries = [],
}) => {
  if (responses.length === 0 && !responses) {
    return [];
  }

  return responses?.map((response, index) => {
    const questionEntry = questionListEntries?.find(
      ([key]) => key === response?.linked_dialogue_item_id,
    )?.[1];

    return {
      key: index + 1,
      text: response?.option,
      recording: response?.recording,
      question: questionEntry?.question || "",
    };
  });
};

const getTrabScriptData = (models) => {
  if (models?.length && models) {
    const speechAnalysisModel = models.find(
      (item) => item?.id === "speech_analysis",
    );

    if (speechAnalysisModel?.words) {
      return speechAnalysisModel.words.map((item) => {
        const aiScore = item?.["Word Score"] || 0;
        let color = getColor(aiScore);

        return {
          aiScore: aiScore,
          text: item?.wordText,
          color: color || "rgba(249, 84, 84, 1)",
        };
      });
    }
  }
  return null;
};

const setupAnalysis = (data, audioData, score) => {
  if (!data || typeof data !== "object") return;
  const formatted = [];
  let totalScore = 0;
  let modelCount = 0;

  if (
    data?.logic_evaluation &&
    data?.logic_evaluation?.length &&
    data?.logic_evaluation?.[0]?.model_data?.["overall_feedback"]
  ) {
    const logicEvalutionData = data?.logic_evaluation?.[0]?.model_data;
    const score = logicEvalutionData?.overall_score || 0;

    const optionData = [];
    const criteria = logicEvalutionData?.criteria;

    if (criteria?.evidence?.feedback) {
      optionData.push({
        id: "evidence",
        label: "Evidence",
        data: {
          ...criteria?.evidence,
          example:
            criteria?.evidence?.example &&
            convertToParagraphWithSpans(criteria?.evidence?.example),
        },
      });
    }
    if (criteria?.coherence?.feedback) {
      optionData.push({
        id: "coherence",
        label: "Coherence",
        data: {
          ...criteria?.coherence,
          example:
            criteria?.coherence?.example &&
            convertToParagraphWithSpans(criteria?.coherence?.example),
        },
      });
    }
    if (criteria?.relevance?.feedback) {
      optionData.push({
        id: "relevance",
        label: "Relevance",
        data: {
          ...criteria?.relevance,
          example:
            criteria?.relevance?.example &&
            convertToParagraphWithSpans(criteria?.relevance?.example),
        },
      });
    }
    if (criteria?.critical_thinking?.feedback) {
      optionData.push({
        id: "critical_thinking",
        label: "Critical",
        data: {
          ...criteria?.critical_thinking,
          example:
            criteria?.critical_thinking?.example &&
            convertToParagraphWithSpans(criteria?.critical_thinking?.example),
        },
      });
    }
    optionData.push({
      id: "character",
      label: "Character",
      data: {
        char_count: logicEvalutionData?.char_count || 0,
        word_count: logicEvalutionData?.word_count || 0,
      },
    });

    formatted.push({
      id: "logic_evaluation",
      label: "Logic evaluation",
      data: { ...logicEvalutionData, optionData },
      score,
      primaryColor: "#febf10",
      bgColor: "#febf1019",
      sideProgress: false,
    });
    totalScore += score;
    modelCount++;
  }

  if (
    data?.speech_analysis &&
    data?.speech_analysis?.length &&
    data?.speech_analysis?.[0]?.model_data?.["Reference"]
  ) {
    const speechAnalysisData = data?.speech_analysis?.[0]?.model_data;
    console.log(speechAnalysisData, "yyyy");
    const score = speechAnalysisData?.["General Score"] || 0;

    const words = Object.values(
      speechAnalysisData?.["Word Phonetic Evaluation"] || {},
    );

    const formattedWords = words?.map((word, idx) => {
      const optionData = [];

      //Phoneme phonetics
      const phonemeData = Object.values(
        word["Phoneme Phonetic Evaluation"] || {},
      );
      const phonemeMappedData = phonemeData?.map((item, idx) => ({
        ...item,
        id: idx + 1,
      }));
      optionData.push({
        id: "phoneme",
        label: "Phoneme phonetics",
        data: phonemeMappedData,
      });

      //Word phonetics
      optionData.push({
        id: "word_phoneme",
        label: "Word phonetics",
        data: {
          score: Math.floor(word?.["Word Score"] || 0),
          syllables: word?.Syllables?.map((item, idx) => ({
            ...item,
            id: idx + 1,
          })),
          syllable_count: word?.["Number Of Syllables"] || 0,
        },
      });

      //Clarity level
      optionData.push({
        id: "clarity",
        label: "Clarity level",
        data: {
          audibility: Math.floor(speechAnalysisData?.Audibility || 0),
          speech_rate: Math.floor(speechAnalysisData?.["Speech Rate"] || 0),
          intonation: Math.floor(speechAnalysisData?.Intonation || 0),
          fluency: Math.floor(speechAnalysisData?.Fluency || 0),
        },
      });

      //Standard assessment
      const testList = [];
      if (speechAnalysisData?.["IELTS Feedback"]) {
        testList.push({
          title: "IELTS",
          score: Math.floor(speechAnalysisData?.["IELTS Score"] || 0),
          feedback: speechAnalysisData?.["IELTS Feedback"],
          color: "#00C2C2",
          total: 9,
        });
      }
      if (speechAnalysisData?.["TOEFL iBT Feedback"]) {
        testList.push({
          title: "TOEFL",
          score: Math.floor(speechAnalysisData?.["TOEFL iBT Score"] || 0),
          feedback: speechAnalysisData?.["TOEFL iBT Feedback"],
          color: "#FEBF10",
          total: 30,
        });
      }
      if (speechAnalysisData?.["TOEIC Feedback"]) {
        testList.push({
          title: "TOEIC",
          score: Math.floor(speechAnalysisData?.["TOEIC Score"] || 0),
          feedback: speechAnalysisData?.["TOEIC Feedback"],
          color: "#30D468",
          total: 200,
        });
      }
      if (speechAnalysisData?.["PTE Feedback"]) {
        testList.push({
          title: "PTE",
          score: Math.floor(speechAnalysisData?.["PTE Score"] || 0),
          feedback: speechAnalysisData?.["PTE Feedback"],
          color: "#9747FF",
          total: 90,
        });
      }
      if (speechAnalysisData?.["CEFR Feedback"]) {
        testList.push({
          title: "CEFR",
          score: speechAnalysisData?.["CEFR Score"] || "",
          feedback: speechAnalysisData?.["CEFR Feedback"],
          color: "#C62F94",
          total: null,
        });
      }

      optionData.push({
        id: "standard_assessment",
        label: "Standard assessment",
        testList,
      });
      return {
        ...word,
        id: idx + 1,
        wordText: word?.Word?.toLowerCase(),
        isGood: word?.["Word Score"] > 45,
        color: getColor(word?.["Word Score"]),
        optionData,
      };
    });

    formatted.push({
      id: "speech_analysis",
      label: "Speech analysis",
      data: speechAnalysisData,
      words: formattedWords,
      score,
      primaryColor: "#30D568",
      bgColor: "#30D4681A",
      sideProgress: true,
      audioData,
    });
    totalScore += score;
    modelCount++;
  }
  if (
    data?.grammar &&
    data?.grammar?.length &&
    (data?.grammar?.[0]?.model_data?.["Original Speech"] ||
      data?.grammar?.[0]?.model_data?.originalText)
  ) {
    const grammarData = data?.grammar?.[0]?.model_data;
    const version = data?.grammar?.[0]?.version;

    const basicData = {
      primaryColor: "#009999",
      bgColor: "#E6F9F9",
      sideProgress: true,

      id: "grammar",
      label: "Grammar",

      data: grammarData,
    };
    if (parseInt(version) === 2) {
      const score = grammarData?.metadata?.overallScore || 0;
      formatted.push({
        version: 2,
        score,
        ...basicData,
      });
      totalScore += score;
      modelCount++;
    } else {
      const score = grammarData?.["Grammar Score"] || 0;
      formatted.push({
        version: 1,

        score,
        ...basicData,
      });
      totalScore += score;
      modelCount++;
    }
  }

  if (
    data?.comprehension?.length &&
    data?.comprehension?.[0]?.attempt_data_batch?.length
  ) {
    const compreshension = data?.comprehension?.[0];
    const score = Math.floor(compreshension?.aggregatedConfidencePercent || 0);

    formatted.push({
      id: "comprehension",
      label: "Comprehension",
      data: compreshension,
      score,
      primaryColor: "#febf10",
      bgColor: "#febf1019",
      sideProgress: true,
      responseText: data?.speech_analysis?.[0]?.model_data?.["Reference"],
    });
    totalScore += score;
    modelCount++;
  }

  let AiScore = 0;
  if (modelCount > 0) {
    AiScore = totalScore / modelCount;
  }
  AiScore = Math.floor(Math.min(100, Math.max(0, AiScore)));

  return {
    AiScore: typeof score === "number" ? Math.floor(score || 0) : 0,
    models: formatted,
  };
};

const quixSelectedModel = (response, aiData) => {
  if (!response || !aiData) return null;

  const audioId = response?.recording?.id || response?.id;
  const objectData = {};

  if (aiData?.speech_analysis && aiData?.speech_analysis?.length) {
    const findData = aiData?.speech_analysis?.find(
      (iten) =>
        iten?.attempt_data?.recording?.id === audioId ||
        iten?.attempt_data?.id === audioId,
    );
    objectData["speech_analysis"] = [findData];
  }
  if (aiData?.grammar && aiData?.grammar?.length) {
    const findData = aiData?.grammar?.find(
      (iten) =>
        iten?.attempt_data?.recording?.id === audioId ||
        iten?.attempt_data?.id === audioId,
    );
    objectData["grammar"] = [findData];
  }
  if (aiData?.comprehension?.length && aiData?.comprehension) {
    const attemptResp = aiData?.comprehension?.[0]?.attempt_data_batch?.[0];

    if (attemptResp?.recording?.id === audioId || attemptResp?.id === audioId) {
      objectData["comprehension"] = aiData?.comprehension;
    }
  }

  return objectData;
};
const dialpgueSelectedModel = (response, aiData) => {
  if (!response || !aiData) return null;

  const audioId = response?.recording?.id || response?.id;
  const objectData = {};

  if (aiData?.speech_analysis && aiData?.speech_analysis?.length) {
    const findData = aiData?.speech_analysis?.find((item) => {
      const attempt = Object.values(item?.attempt_data || {})?.[0];
      return attempt?.recording?.id === audioId || attempt?.id === audioId;
    });
    objectData["speech_analysis"] = [findData];
  }
  if (aiData?.grammar && aiData?.grammar?.length) {
    const findData = aiData?.grammar?.find((item) => {
      const attempt = Object.values(item?.attempt_data || {})?.[0];
      return attempt?.recording?.id === audioId || attempt?.id === audioId;
    });
    objectData["grammar"] = [findData];
  }

  return objectData;
};

const grammarFeekbackResult = (originalText, feedbackCorrection, feedbacks) => {
  if (!originalText || !feedbackCorrection) return [];

  // Attach feedback and feedbackPosition to each correction
  const correctionsWithFeedback = feedbackCorrection.map(
    (correction, index) => ({
      ...correction,
      feedback: feedbacks?.[index] || null,
      feedbackPosition: index + 1,
    }),
  );

  const result = [];
  let correctionIndex = 0;

  // Tokenize originalText into words and punctuation
  const originalTokens = originalText.match(/\w+|[^\s\w]+/g) || [];
  let tokenIndex = 0;

  while (
    tokenIndex < originalTokens.length ||
    correctionIndex < correctionsWithFeedback.length
  ) {
    const token = originalTokens[tokenIndex];
    const correction = correctionsWithFeedback[correctionIndex];

    // Handle substituted or formatting corrections
    if (
      correction &&
      (correction.operation === "substituted" ||
        correction.operation === "formatting")
    ) {
      const originalWordsFromCorrection =
        correction.original_word?.match(/\w+|[^\s\w]+/g) || [];
      const slice = originalTokens
        .slice(tokenIndex, tokenIndex + originalWordsFromCorrection.length)
        .join(""); // 🔥 Key fix: no space between tokens

      if (slice === correction.original_word) {
        result.push({
          text: correction.original_word,
          correct: correction.replacement_word,
          position: result.length + 1,
          operation: correction.operation,
          feedback: correction.feedback,
          feedbackPosition: correction.feedbackPosition,
        });

        tokenIndex += originalWordsFromCorrection.length;
        correctionIndex++;
        continue;
      }
    }

    // Handle inserted correction
    if (correction && correction.operation === "inserted") {
      result.push({
        text: correction.word.trim(),
        correct: correction.word.trim(),
        position: result.length + 1,
        operation: correction.operation,
        feedback: correction.feedback,
        feedbackPosition: correction.feedbackPosition,
      });

      correctionIndex++;
      continue;
    }

    // Default: push original token as-is
    if (tokenIndex < originalTokens.length) {
      result.push({
        text: token,
      });
      tokenIndex++;
    } else {
      correctionIndex++;
    }
  }

  return result;
};

const renderCorrectedSentence = (feedbackData) => {
  if (!feedbackData || feedbackData.length === 0) {
    return [];
  }

  const result = [];

  for (const item of feedbackData) {
    const textToDisplay = item.correct !== undefined ? item.correct : item.text;

    const hasCorrection = !!item.operation;

    const lastChar = textToDisplay.slice(-1);
    const isPunctuation = /[.,!?;:]/.test(lastChar);

    result.push({
      text: textToDisplay,
      highlight: hasCorrection,
      addSpace: !isPunctuation,
    });
  }

  return result;
};

const grammarCorrectResult = (correctedText, feedbackCorrection) => {
  if (!correctedText || !feedbackCorrection || !feedbackCorrection?.length) {
    return [correctedText];
  }

  // Combine corrections with their feedback for easier access
  const combinedCorrections = feedbackCorrection.map((correction, index) => ({
    ...correction,
    id: index, // Add a unique ID for React keys
  }));

  const correctWords = correctedText.split(/\s+/);
  const result = [];
  let correctWordIndex = 0;

  // Use a temporary counter to match the position in the correction data
  let positionCounter = 1;

  while (
    correctWordIndex < correctWords.length ||
    combinedCorrections.length > 0
  ) {
    const word = correctWords[correctWordIndex];
    const correction = combinedCorrections[0]; // Always check the first correction

    if (correction && correction.position === positionCounter) {
      // This is a corrected word, wrap it in a span
      const highlightableWord = correctWords
        .slice(
          correctWordIndex,
          correctWordIndex + correction.replacement_word.split(/\s+/).length,
        )
        .join(" ");

      result.push({
        text: highlightableWord,
        highlight: true,
        id: correction.id,
      });

      // Advance our word index by the length of the corrected words
      correctWordIndex += correction.replacement_word.split(/\s+/).length;
      positionCounter += correction.replacement_word.split(/\s+/).length;

      // Remove the correction from the array since we've handled it
      combinedCorrections.shift();
    } else {
      // This is a normal, uncorrected word
      if (word !== undefined) {
        result.push({ text: word, highlight: false });
        correctWordIndex++;
        positionCounter++;
      } else {
        break;
      }
    }
  }

  return result;
};
const grammerCorrectParagraph = (data) => {
  if (!data) return;
  let paragraph = "";

  data?.forEach((item) => {
    if (item?.highlight) {
      paragraph += `<span>${item?.text}</span> `;
    } else {
      paragraph += `${item?.text} `;
    }
  });

  paragraph = paragraph?.trim();

  return paragraph;
};
const formatNumber = (number) => {
  if (!number && typeof number !== "number") return "0.0";

  const formattedNumber = number?.toFixed(1);
  return formattedNumber;
};

const grammarFindOperation = (feedbackCorrection, operationIndex) => {
  if (!feedbackCorrection && typeof operationIndex !== "number") return;
  const substitutedCorrections = feedbackCorrection.filter((correction) =>
    ["substituted", "formatting"].includes(correction?.operation),
  );
  return substitutedCorrections[operationIndex ?? -1] || null;
};
function toRGBA(rgbaString, alpha = 1) {
  const [r, g, b] = rgbaString.match(/\d+/g).map(Number);
  return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}

const getQuestionInfo = (question) => {
  let type = "";
  if (question?.type === "SOUND_PLAY") type = "sound-play";
  else if (question?.question_data?.type === "DIALOGUE") {
    if (
      Object.values(question?.question_data?.dialogues_data || {})?.[0]
        ?.type === "Scripted"
    )
      type = "dialogue-scripted";
    else type = "dialogue-unscripted";
  } else if (question?.question_data?.type === "WORD_PLAY") {
    if (question?.question_data?.answer_format_data?.type === "Multiple Choice")
      type = "word-play-multiple-choice";
    else type = "word-play-text";
  } else if (question?.type === "QUIZ") {
    if (
      question?.question_data?.question_data?.type === "MultipleChoice" ||
      question?.question_data?.question_data?.type === "Multiple Choice"
    )
      type = "quiz-multiple-choice";
    else if (question?.question_data?.question_data?.type === "UnScripted")
      type = "quiz-unscripted";
    else if (question?.question_data?.question_data?.type === "Written")
      type = "quiz-written";
    else type = "quiz-scripted";
  } else if (question?.type === "ESSAY") {
    if (question?.question_data?.config?.type === "Scripted")
      type = "essay-scripted";
    else if (question?.question_data?.config?.type === "Written")
      type = "essay-written";
    else type = "essay-unscripted";
  } else if (question?.question_data?.type === "READING") type = "reading";
  else if (question?.type === "MATCH_PAIR") type = "match-pair";
  else type = "";

  return { type, data: question };
};
const quizWrittenSelectedModel = (response, aiData) => {
  if (!response || !aiData) return null;
  const index = response?.index || 0;
  const objectData = {};

  if (aiData?.grammar?.[index] && aiData?.grammar?.length) {
    const findData = aiData?.grammar?.[index];
    objectData["grammar"] = [findData];
  }
  if (
    aiData?.comprehension?.length &&
    aiData?.comprehension?.[0] &&
    index === 0
  ) {
    objectData["comprehension"] = aiData?.comprehension;
  }
  return objectData;
};

const validateModels = (modelsData, modelTypes = []) => {
  const labels = {
    logic_evaluation: "Logic evaluation",
    speech_analysis: "Speech analysis",
    grammar: "Grammar",
    comprehension: "Comprehension",
  };

  const orderedTypes = [
    "logic_evaluation",
    "speech_analysis",
    "grammar",
    "comprehension",
  ];

  const existingModels = modelsData?.models || [];

  const validatedModels = orderedTypes
    .filter((type) => modelTypes.includes(type))
    .map((type) => {
      const existing = existingModels.find((m) => m.id === type);

      if (existing) {
        return {
          ...existing,
          isEmpty: false,
          sideProgress: type !== "logic_evaluation",
        };
      }

      return {
        id: type,
        label: labels[type],
        score: 0,
        isEmpty: true,
        sideProgress: type !== "logic_evaluation",
      };
    });

  return { ...modelsData, models: validatedModels };
};

const useReportUtils = () => {
  const { findText } = useTranslation(wordstore);

  const boundSetupAnalysis = (data, audioData, score) =>
    setupAnalysis(data, audioData, score, findText);

  return {
    renderCorrectedSentence,
    choiceListAndAnswer,
    hasAnswerData,
    quizResponses,
    dialogueResponses,
    setupAnalysis: boundSetupAnalysis,
    getTrabScriptData,
    quixSelectedModel,
    dialpgueSelectedModel,
    grammarFeekbackResult,
    grammarCorrectResult,
    grammerCorrectParagraph,
    formatNumber,
    getColor,
    grammarFindOperation,
    toRGBA,
    getQuestionInfo,
    quizWrittenSelectedModel,
    validateModels,
  };
};

export default useReportUtils;
