const Course = require("../models/courseModel");
const APIFeatures = require("../utils/ApiFeatures");

// --- Helper: Process Uploaded Files ---
const processUploadedFiles = (req) => {
  if (!req.files) return;
  if (req.files.coverImage)
    req.body.coverImage = req.files.coverImage[0].filename;
  if (req.files.promoVideo)
    req.body.promoVideo = req.files.promoVideo[0].filename;
  if (req.files.images)
    req.body.images = req.files.images.map((file) => file.filename);
  if (req.files.certificateTemplate) {
    req.body.certificateTemplate = req.files.certificateTemplate[0].filename;
  }
};

// --- Helper: Format Input for Embedded Schema ---
// ✅ Fixes "400 Bad Request" by converting ID strings to Objects
const formatInputData = (body) => {
  // 1. Handle Stacks (String -> Array)
  if (typeof body.stacks === "string") {
    body.stacks = body.stacks.split(",").map((s) => s.trim());
  }

  // 2. Handle Instructors (String/Array -> Array of Objects)
  if (body.instructors) {
    // Ensure it's an array (FormData might send a single string if only 1 item)
    let inst = body.instructors;
    if (!Array.isArray(inst)) {
      inst = [inst];
    }
    // Convert ["ID"] to [{ _id: "ID" }] so Mongoose accepts it
    body.instructors = inst.map((id) => {
      return typeof id === "string" ? { _id: id } : id;
    });
  }

  // 3. Handle Campus (String -> Object)
  if (body.campus && typeof body.campus === "string") {
    body.campus = { _id: body.campus };
  }

  // 4. Handle Category (String -> Object)
  if (body.category && typeof body.category === "string") {
    body.category = { _id: body.category };
  }
};

exports.getAllCourses = async (req, res) => {
  try {
    if (!req.query.limit) req.query.limit = "100";

    // 🚀 FAST QUERY: No populate needed! The names are already in the docs.
    const features = new APIFeatures(Course.find(), req.query)
      .filter()
      .sort()
      .limitFields()
      .paginate();

    const courses = await features.query;

    res.status(200).json({
      status: "success",
      results: courses.length,
      data: { courses },
    });
  } catch (err) {
    res.status(400).json({ status: "fail", message: err.message });
  }
};

exports.getCourse = async (req, res) => {
  try {
    const course = await Course.findById(req.params.id);
    if (!course)
      return res
        .status(404)
        .json({ status: "fail", message: "Course not found" });

    res.status(200).json({ status: "success", data: { course } });
  } catch (err) {
    res.status(400).json({ status: "fail", message: err.message });
  }
};

exports.createCourse = async (req, res) => {
  try {
    processUploadedFiles(req);

    // ✅ FIX: Format the IDs into Objects before creating
    formatInputData(req.body);

    // The Pre-Save hook in the Model will handle fetching the names
    const newCourse = await Course.create(req.body);

    res.status(201).json({ status: "success", data: { course: newCourse } });
  } catch (err) {
    res
      .status(400)
      .json({ status: "fail", message: "Invalid data", error: err.message });
  }
};

exports.updateCourse = async (req, res) => {
  try {
    processUploadedFiles(req);

    // ✅ FIX: Format the IDs into Objects before updating
    formatInputData(req.body);

    const course = await Course.findById(req.params.id);
    if (!course) return res.status(404).json({ message: "Course not found" });

    // Apply updates manually to trigger the 'save' hook
    Object.keys(req.body).forEach((key) => {
      course[key] = req.body[key];
    });

    // Save triggers the pre('save') hook to update embedded names
    await course.save();

    res.status(200).json({ status: "success", data: { course } });
  } catch (err) {
    res.status(400).json({ status: "fail", message: err.message });
  }
};

exports.deleteCourse = async (req, res) => {
  try {
    const course = await Course.findByIdAndDelete(req.params.id);
    if (!course) return res.status(404).json({ message: "Course not found" });
    res.status(204).json({ status: "success", data: null });
  } catch (err) {
    res.status(400).json({ status: "fail", message: err.message });
  }
};
