export const lessonContentTypes = ["VIDEO", "LECTURE", "ACTIVITY", "QUIZ", "FINAL_EXAM"] as const;

export type LessonContentType = (typeof lessonContentTypes)[number];

export const lessonQuestionKinds = ["TRUE_FALSE", "MULTIPLE_CHOICE"] as const;

export type LessonQuestionKind = (typeof lessonQuestionKinds)[number];

export type LessonQuestionOption = {
  id: string;
  text: string;
  isCorrect: boolean;
};

export type LessonQuestion = {
  id: string;
  kind: LessonQuestionKind;
  prompt: string;
  explanation: string;
  options: LessonQuestionOption[];
};

export type LessonActivityMeta = {
  instructions: string;
  passingScorePercent: number;
  questions: LessonQuestion[];
};

type LessonDescriptionMeta = {
  text: string;
  contentType: LessonContentType;
  materialUrl: string | null;
  lectureContent: string;
  activity: LessonActivityMeta | null;
};

const lessonTypeAliases: Record<string, LessonContentType> = {
  VIDEO: "VIDEO",
  LECTURE: "LECTURE",
  LECTURA: "LECTURE",
  READING: "LECTURE",
  ACTIVITY: "ACTIVITY",
  ACTIVIDAD: "ACTIVITY",
  QUIZ: "QUIZ",
  EVALUACION: "QUIZ",
  EVALUACIÓN: "QUIZ",
  FINAL_EXAM: "FINAL_EXAM",
  EXAMEN_FINAL: "FINAL_EXAM",
  EXAMENFINAL: "FINAL_EXAM",
  EVALUACION_FINAL: "FINAL_EXAM",
  EVALUACIÓN_FINAL: "FINAL_EXAM",
};

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

function asString(value: unknown): string {
  return typeof value === "string" ? value.trim() : "";
}

function asNumber(value: unknown): number | null {
  if (typeof value === "number" && Number.isFinite(value)) return value;
  if (typeof value === "string" && value.trim()) {
    const parsed = Number(value);
    if (Number.isFinite(parsed)) return parsed;
  }
  return null;
}

function normalizeType(value: string): LessonContentType {
  const normalized = value.trim().toUpperCase();
  return lessonTypeAliases[normalized] ?? "VIDEO";
}

function getDescriptionText(input: unknown): string {
  if (typeof input === "string") return input.trim();
  if (isRecord(input)) {
    const direct = asString(input.text);
    if (direct) return direct;
    const es = asString(input.es);
    if (es) return es;
    const en = asString(input.en);
    if (en) return en;
    const summary = asString(input.summary);
    if (summary) return summary;
  }
  return "";
}

function normalizeQuestionKind(value: unknown): LessonQuestionKind {
  const raw = asString(value).toUpperCase();
  return raw === "TRUE_FALSE" ? "TRUE_FALSE" : "MULTIPLE_CHOICE";
}

function parseQuestionOptions(value: unknown, kind: LessonQuestionKind): LessonQuestionOption[] {
  if (!Array.isArray(value)) {
    if (kind === "TRUE_FALSE") {
      return [
        { id: "true", text: "Verdadero", isCorrect: true },
        { id: "false", text: "Falso", isCorrect: false },
      ];
    }
    return [];
  }

  const options = value
    .map((option, index) => {
      if (!isRecord(option)) return null;
      const id = asString(option.id) || `opt-${index + 1}`;
      const text = asString(option.text);
      const isCorrect = Boolean(option.isCorrect);
      if (!text) return null;
      return { id, text, isCorrect };
    })
    .filter((option): option is LessonQuestionOption => option !== null);

  if (kind === "TRUE_FALSE") {
    const hasTrue = options.find((option) => option.id === "true" || option.text.toLowerCase() === "verdadero");
    const hasFalse = options.find((option) => option.id === "false" || option.text.toLowerCase() === "falso");
    if (!hasTrue || !hasFalse) {
      const correctIndex = options.findIndex((option) => option.isCorrect);
      return [
        { id: "true", text: "Verdadero", isCorrect: correctIndex !== 1 },
        { id: "false", text: "Falso", isCorrect: correctIndex === 1 },
      ];
    }
  }

  return options;
}

function parseQuestion(value: unknown, index: number): LessonQuestion | null {
  if (!isRecord(value)) return null;
  const kind = normalizeQuestionKind(value.kind ?? value.type);
  const id = asString(value.id) || `q-${index + 1}`;
  const prompt = asString(value.prompt ?? value.question);
  const explanation = asString(value.explanation);
  const options = parseQuestionOptions(value.options, kind);

  if (!prompt) return null;
  if (options.length < 2) return null;

  const hasCorrect = options.some((option) => option.isCorrect);
  const normalizedOptions = hasCorrect ? options : options.map((option, optIndex) => ({ ...option, isCorrect: optIndex === 0 }));

  return {
    id,
    kind,
    prompt,
    explanation,
    options: normalizedOptions,
  };
}

function normalizePassingScore(value: unknown, fallback: number): number {
  const parsed = asNumber(value);
  if (parsed == null) return fallback;
  return Math.max(0, Math.min(100, Math.round(parsed)));
}

function parseActivityMeta(description: Record<string, unknown>): LessonActivityMeta | null {
  const activityRaw =
    (isRecord(description.activity) && description.activity) ||
    (isRecord(description.quiz) && description.quiz) ||
    (isRecord(description.exercise) && description.exercise) ||
    null;

  if (!activityRaw) return null;

  const instructions = asString(activityRaw.instructions ?? activityRaw.intro ?? description.es ?? description.text);
  const passingScorePercent = normalizePassingScore(activityRaw.passingScorePercent, 70);
  const questionsRaw = Array.isArray(activityRaw.questions) ? activityRaw.questions : [];
  const questions = questionsRaw
    .map((question, index) => parseQuestion(question, index))
    .filter((question): question is LessonQuestion => question !== null);

  if (questions.length === 0) return null;

  return {
    instructions,
    passingScorePercent,
    questions,
  };
}

export function parseLessonDescriptionMeta(description: unknown): LessonDescriptionMeta {
  if (!isRecord(description)) {
    const fallbackText = getDescriptionText(description);
    return {
      text: fallbackText,
      contentType: "VIDEO",
      materialUrl: null,
      lectureContent: fallbackText,
      activity: null,
    };
  }

  const contentTypeRaw = asString(description.contentType) || asString(description.kind) || asString(description.type);
  const materialUrl =
    asString(description.materialUrl) ||
    asString(description.resourceUrl) ||
    asString(description.pdfUrl) ||
    asString(description.attachmentUrl) ||
    "";
  const text = getDescriptionText(description);
  const lectureContent = asString(description.lectureContent) || asString(description.content) || text;
  const activity = parseActivityMeta(description);

  return {
    text,
    contentType: normalizeType(contentTypeRaw || "VIDEO"),
    materialUrl: materialUrl || null,
    lectureContent,
    activity,
  };
}

export function buildLessonDescriptionMeta(input: {
  text: string;
  contentType: LessonContentType;
  materialUrl?: string | null;
  lectureContent?: string | null;
  activity?: LessonActivityMeta | null;
}): Record<string, unknown> {
  const payload: Record<string, unknown> = {
    contentType: input.contentType,
  };

  const text = input.text.trim();
  if (text) payload.es = text;

  const materialUrl = (input.materialUrl ?? "").trim();
  if (materialUrl) payload.materialUrl = materialUrl;

  const lectureContent = (input.lectureContent ?? "").trim();
  if (lectureContent) payload.lectureContent = lectureContent;

  const activity = input.activity;
  if (activity && activity.questions.length > 0) {
    payload.activity = {
      instructions: activity.instructions.trim(),
      passingScorePercent: Math.max(0, Math.min(100, Math.round(activity.passingScorePercent))),
      questions: activity.questions.map((question, qIndex) => {
        const questionId = question.id.trim() || `q-${qIndex + 1}`;
        const prompt = question.prompt.trim();
        const explanation = question.explanation.trim();
        const kind: LessonQuestionKind = question.kind === "TRUE_FALSE" ? "TRUE_FALSE" : "MULTIPLE_CHOICE";
        const options = question.options
          .map((option, optionIndex) => {
            const optionId = option.id.trim() || `opt-${optionIndex + 1}`;
            const optionText = option.text.trim();
            if (!optionText) return null;
            return {
              id: optionId,
              text: optionText,
              isCorrect: Boolean(option.isCorrect),
            };
          })
          .filter((option): option is LessonQuestionOption => option !== null);
        const hasCorrect = options.some((option) => option.isCorrect);
        const normalizedOptions = hasCorrect ? options : options.map((option, optionIndex) => ({ ...option, isCorrect: optionIndex === 0 }));
        return {
          id: questionId,
          kind,
          prompt,
          explanation,
          options: normalizedOptions,
        };
      }),
    };
  }

  return payload;
}

export function getLessonContentTypeLabel(contentType: LessonContentType): string {
  if (contentType === "LECTURE") return "Lectura";
  if (contentType === "ACTIVITY") return "Actividad";
  if (contentType === "QUIZ") return "Quiz";
  if (contentType === "FINAL_EXAM") return "Evaluación final";
  return "Video";
}

export function isFinalExam(contentType: LessonContentType): boolean {
  return contentType === "FINAL_EXAM";
}
