import {
  ReturnProcessAnswers,
  ReturnProcessQuestion,
  ReturnProcessQuestionKey,
  ReturnProcessQuestionType,
} from '../../models';
import { ReturnProcessQuestionSchema } from '../../questions';
import {
  getAllNextQuestions,
  getNextQuestion,
} from './get-next-question.helper';

export const calculateLongestQuestionDepth = (
  questions: ReturnProcessQuestion[],
  answers: ReturnProcessAnswers,
): number => {
  if (questions.length === 0) {
    return 0;
  }
  return internalCalculateLongestQuestionDepth(
    questions,
    answers,
    questions[0].key,
  ).depth;
};

export const internalCalculateLongestQuestionDepth = (
  questions: ReturnProcessQuestion[],
  answers: ReturnProcessAnswers,
  questionKey: ReturnProcessQuestionKey,
): { depth: number; nextQuestion?: ReturnProcessQuestionKey } => {
  // 1) Frageobjekt finden
  const question = questions.find((q) => q.key === questionKey);
  if (!question) {
    return { depth: 0 };
  }

  // 2) Info-Fragen überspringen (zählen nicht zur Tiefe)
  if (question.type === ReturnProcessQuestionType.Info) {
    const nextKey = question.nextQuestion;
    if (nextKey) {
      // direkt zum Kind ohne +1
      return internalCalculateLongestQuestionDepth(questions, answers, nextKey);
    }
    // keine Folgefrage: Tiefe 0
    return { depth: 0 };
  }

  // 3) Group-Fragen entpacken (zählen ebenfalls nicht selbst zur Tiefe)
  if (question.type === ReturnProcessQuestionType.Group) {
    const combined = [...question.questions, ...questions];
    return internalCalculateLongestQuestionDepth(
      combined,
      answers,
      question.questions[0].key,
    );
  }

  // 4) Prüfen, ob wir schon eine (gültige) Antwort für diese Frage haben
  const schema = ReturnProcessQuestionSchema[question.key];
  const parseResult = schema.safeParse(answers[question.key]);

  if (parseResult.success) {
    // 4a) Gibt es eine gezielte Folgefrage?
    const nextKey = getNextQuestion(question, answers);
    if (nextKey) {
      const { depth: childDepth, nextQuestion: childNext } =
        internalCalculateLongestQuestionDepth(questions, answers, nextKey);
      // +1, weil diese Frage selbst zählt (nicht Info, nicht Group)
      return {
        depth: childDepth + 1,
        nextQuestion: childNext,
      };
    }
    // 4b) Ende des Pfads: zählt noch einmal +1 für diese Frage
    return { depth: 1 };
  }

  // 5) Noch keine valide Antwort → alle möglichen Folgefragen ausloten
  const possibleNext = getAllNextQuestions(question) || [];
  if (possibleNext.length > 0) {
    let maxDepth = 0;
    let bestNext: ReturnProcessQuestionKey | undefined;
    for (const nxt of possibleNext) {
      const { depth: d } = internalCalculateLongestQuestionDepth(
        questions,
        answers,
        nxt,
      );
      // +1, weil diese Frage selbst zählt
      if (d + 1 > maxDepth) {
        maxDepth = d + 1;
        bestNext = nxt;
      }
    }
    return { depth: maxDepth, nextQuestion: bestNext };
  }

  // 6) Keine weiteren Pfade → nur diese Frage zählt
  return { depth: 1 };
};
