// lib/canvas/api.js — render the neutral Canvas IR (map.js) into Canvas *Classic Quizzes*
// REST payloads. Same IR the .zip path uses, so question mapping lives in exactly one place.
// Used by the server route app/api/canvas/route.js (browser→Canvas is blocked by CORS).

export function normalizeBaseUrl(url) {
  let u = String(url || "").trim();
  if (!u) return "";
  if (!/^https?:\/\//i.test(u)) u = "https://" + u;
  return u.replace(/\/+$/, "");
}

// Strip tags + decode the few entities we emit, for the plain answer_text fallback.
function stripTags(html) {
  return String(html || "")
    .replace(/<[^>]+>/g, "")
    .replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&").replace(/&quot;/g, '"');
}

// IR.quiz -> body for POST /api/v1/courses/:id/quizzes
export function quizPayload(ir) {
  const q = ir.quiz;
  const quiz = {
    title: q.title,
    description: q.description || "",
    quiz_type: q.quizType,
    shuffle_answers: !!q.shuffleAnswers,
    allowed_attempts: q.allowedAttempts,
    scoring_policy: q.scoringPolicy,
    show_correct_answers: q.showCorrectAnswers !== false,
    one_question_at_a_time: !!q.oneQuestionAtATime,
    cant_go_back: !!(q.oneQuestionAtATime && q.cantGoBack),
    published: false, // import unpublished so the teacher reviews before students see it
  };
  if (q.timeLimit !== "" && q.timeLimit != null) quiz.time_limit = q.timeLimit;
  if (q.accessCode) quiz.access_code = q.accessCode;
  if (q.dueAt) quiz.due_at = q.dueAt;
  if (q.unlockAt) quiz.unlock_at = q.unlockAt;
  if (q.lockAt) quiz.lock_at = q.lockAt;
  return { quiz };
}

// IR.items -> array of bodies for POST /api/v1/courses/:id/quizzes/:qid/questions
export function questionPayloads(ir) {
  return ir.items.map((it, i) => ({ question: questionBody(it, i + 1) }));
}

function questionBody(it, position) {
  const body = {
    question_name: it.title || `Question ${position}`,
    question_text: it.promptHtml || "",
    question_type: it.canvasType,
    points_possible: it.points || 0,
    position,
  };
  if (it.feedback?.neutralHtml) body.neutral_comments_html = it.feedback.neutralHtml;

  switch (it.canvasType) {
    case "multiple_choice_question":
    case "true_false_question":
      body.answers = it.choices.map((c) => ({
        answer_html: c.html, answer_text: stripTags(c.html), answer_weight: c.correct ? 100 : 0,
      }));
      break;
    case "fill_in_multiple_blanks_question":
      body.answers = it.blanks.flatMap((b) =>
        b.answers.map((a) => ({ answer_text: a.textPlain, answer_weight: 100, blank_id: b.name })));
      break;
    case "matching_question": {
      const rightText = (ident) => (it.rights.find((r) => r.ident === ident)?.textPlain) || "";
      body.answers = it.lefts.map((l) => ({
        answer_match_left: l.textPlain,
        answer_match_right: rightText(l.correctRightIdent),
        answer_weight: 100,
      }));
      const used = new Set(it.lefts.map((l) => l.correctRightIdent));
      const distractors = it.rights.filter((r) => !used.has(r.ident)).map((r) => r.textPlain);
      if (distractors.length) body.matching_answer_incorrect_matches = distractors.join("\n");
      break;
    }
    case "essay_question":
    case "text_only_question":
    default:
      body.answers = [];
  }
  return body;
}
