import { pool } from "../config/db.js";
import { ApiError } from "../utils/ApiError.js";
import { attachCombinedMetadata, loadCombinedQuestionMaps } from "../utils/oracCombinedQuestionEnrichment.js";
import { sortSectionQuestionsRpnLast } from "../utils/oracSortSectionQuestionsRpnLast.js";

function toPositiveInteger(value, fieldName) {
  const parsed = Number(value);
  if (!Number.isInteger(parsed) || parsed <= 0) {
    throw new ApiError(400, `${fieldName} must be a positive integer`);
  }
  return parsed;
}

export async function getSectionWithQuestions(req, res, next) {
  try {
    const sectionId = toPositiveInteger(req.params.section_id, "section_id");

    const [sectionRows] = await pool.query(
      "SELECT * FROM `orac_section_details` WHERE `section_id` = ? LIMIT 1",
      [sectionId]
    );
    if (!sectionRows.length) {
      throw new ApiError(404, "Section not found");
    }

    const [questions] = await pool.query(
      `SELECT
         q.question_id,
         q.question,
         q.question_type_id,
         qt.question_type
       FROM orac_section_question_map m
       JOIN orac_questions q ON q.question_id = m.question_id
       LEFT JOIN orac_question_type qt ON qt.question_type_id = q.question_type_id
       WHERE m.section_id = ?
       ORDER BY q.question_id`,
      [sectionId]
    );

    const maps = await loadCombinedQuestionMaps();

    const questionIds = questions.map((q) => q.question_id);
    let optionsMap = {};

    if (questionIds.length) {
      const [options] = await pool.query(
        `SELECT question_options_id, question_id, _options
         FROM orac_question_options
         WHERE question_id IN (?)
         ORDER BY question_options_id`,
        [questionIds]
      );
      for (const opt of options) {
        if (!optionsMap[opt.question_id]) {
          optionsMap[opt.question_id] = [];
        }
        optionsMap[opt.question_id].push({
          question_options_id: opt.question_options_id,
          option: opt._options
        });
      }
    }

    const questionsWithOptions = questions.map((q) =>
      attachCombinedMetadata(
        {
          ...q,
          options: optionsMap[q.question_id] || []
        },
        maps
      )
    );

    return res.json({
      ...sectionRows[0],
      questions: sortSectionQuestionsRpnLast(questionsWithOptions)
    });
  } catch (error) {
    return next(error);
  }
}

export async function createSectionQuestionMap(req, res, next) {
  try {
    const sectionId = toPositiveInteger(req.body?.section_id, "section_id");
    const questionId = toPositiveInteger(req.body?.question_id, "question_id");

    const [sectionRows] = await pool.query(
      "SELECT 1 FROM `orac_section_details` WHERE `section_id` = ? LIMIT 1",
      [sectionId]
    );
    if (!sectionRows.length) {
      throw new ApiError(404, "Section not found for provided section_id");
    }

    const [questionRows] = await pool.query(
      "SELECT 1 FROM `orac_questions` WHERE `question_id` = ? LIMIT 1",
      [questionId]
    );
    if (!questionRows.length) {
      throw new ApiError(404, "Question not found for provided question_id");
    }

    const [existingRows] = await pool.query(
      "SELECT 1 FROM `orac_section_question_map` WHERE `section_id` = ? AND `question_id` = ? LIMIT 1",
      [sectionId, questionId]
    );
    if (existingRows.length) {
      throw new ApiError(409, "Question is already mapped to this section");
    }

    await pool.query(
      "INSERT INTO `orac_section_question_map` (`section_id`, `question_id`) VALUES (?, ?)",
      [sectionId, questionId]
    );

    return res.status(201).json({
      message: "Question mapped to section successfully",
      data: {
        section_id: sectionId,
        question_id: questionId
      }
    });
  } catch (error) {
    return next(error);
  }
}
