const mongoose = require("mongoose");
const { addBaseUrlToImages } = require("../utils/imageHelper");
const AboutUs = require("../models/aboutUs");
const Blog = require("../models/blog");
const jsonHelper = require("../utils/jsonHelper");
const {
  validateLengthRules,
  summarizeLengthErrors,
} = require("../utils/lengthValidation");
const {
  ABOUT_US_LENGTH_RULES,
} = require("../constants/contentLengthRules");
const writeAuditLog = require("../audit/writeAuditLog");
const diffObject = require("../audit/diffObject");
const AUDIT_ACTIONS = require("../constants/auditAction");

const ABOUT_NEWS_FALLBACK_THUMBNAIL = "/uploads/blog/7281.jpg";
const ABOUT_NEWS_FALLBACK_AVATAR = "/assets/img/home-1/news/client.png";
const ABOUT_NEWS_PLACEHOLDER_THUMBNAIL =
  "img/inner-page/news-details/details-1.jpg";
const ABOUT_MISSION_ITEM_ICON = "/assets/img/home-1/icon/01.svg";

const normalizePath = (value) => {
  if (!value || typeof value !== "string") return "";
  if (value.startsWith("http://") || value.startsWith("https://")) return value;
  if (value.startsWith("/")) return value;
  return `/${value}`;
};

const isPlaceholderNewsThumbnail = (value) => {
  if (!value || typeof value !== "string") return true;

  const normalized = value.trim().toLowerCase();
  return (
    normalized === ABOUT_NEWS_PLACEHOLDER_THUMBNAIL ||
    normalized === `/${ABOUT_NEWS_PLACEHOLDER_THUMBNAIL}` ||
    normalized.endsWith("/inner-page/news-details/details-1.jpg") ||
    normalized.endsWith("news-details/details-1.jpg")
  );
};

const sanitizeAboutSection = (section = {}, allowedKeys = []) => {
  const sanitized = {};

  allowedKeys.forEach((key) => {
    if (section[key] !== undefined) {
      sanitized[key] = section[key];
    }
  });

  return sanitized;
};

const sanitizeMissionItems = (items) => {
  if (!Array.isArray(items)) return [];

  return items
    .map((item = {}) => ({
      icon: ABOUT_MISSION_ITEM_ICON,
      label:
        typeof item.label === "string"
          ? item.label
          : typeof item.title === "string"
            ? item.title
            : "",
      description: typeof item.description === "string" ? item.description : "",
    }))
    .filter((item) => item.label || item.description);
};

const buildCanonicalAboutData = (data) => {
  const source = data || {};

  return {
    hero: sanitizeAboutSection(source.hero, [
      "title",
      "breadcrumb",
      "backgroundImage",
    ]),
    intro: sanitizeAboutSection(source.intro, [
      "subheading",
      "heading",
      "description",
      "image",
    ]),
    mission: {
      ...sanitizeAboutSection(source.mission, [
        "subheading",
        "heading",
        "description",
        "features",
        "ctaButton",
      ]),
      items: sanitizeMissionItems(source.mission?.items),
      images: sanitizeAboutSection(source.mission?.images, [
        "main",
        "secondary",
      ]),
    },
    features: {
      ...sanitizeAboutSection(source.features, [
        "backgroundImage",
        "subheading",
        "heading",
        "description",
        "image",
        "items",
        "ctaButton",
      ]),
    },
    news: {
      ...sanitizeAboutSection(source.news, [
        "subheading",
        "heading",
        "ctaButton",
        "selectedBlogIds",
      ]),
      items: Array.isArray(source.news?.items) ? source.news.items : [],
    },
  };
};

const resolveBlogImage = (value, fallback = ABOUT_NEWS_FALLBACK_THUMBNAIL) => {
  if (!value || isPlaceholderNewsThumbnail(value)) {
    return fallback;
  }

  return normalizePath(value);
};

const toObjectId = (value) => {
  const stringValue = value && typeof value.toString === "function" ? value.toString() : "";
  return mongoose.isValidObjectId(stringValue)
    ? new mongoose.Types.ObjectId(stringValue)
    : null;
};

const resolveNewsItem = (blog, index = 0) => {
  const fallbackThumbs = [
    ABOUT_NEWS_FALLBACK_THUMBNAIL,
    "/uploads/about/news-1.jpg",
    "/uploads/about/news-3.jpg",
  ];

  return {
    title: blog.title,
    category: blog.category && blog.category[0] ? blog.category[0] : "Visa",
    date:
      blog.publishedAt ||
      new Date(blog.createdAt).toLocaleDateString("en-GB", {
        day: "numeric",
        month: "long",
        year: "numeric",
      }),
    comments: blog.commentsCount || 0,
    author: {
      name: blog.author || "Admin",
      avatar: ABOUT_NEWS_FALLBACK_AVATAR,
    },
    link: `/blog/${blog.slug}`,
    thumbnail: resolveBlogImage(
      blog.featuredImage,
      fallbackThumbs[index % fallbackThumbs.length],
    ),
  };
};

const handleLengthValidation = (validation, req, res, options = {}) => {
  const message =
    summarizeLengthErrors(validation, 3) || "One or more fields exceed the allowed length.";

  if (options.json) {
    return res.status(400).json({
      success: false,
      error: message,
      errors: validation.errors,
    });
  }

  req.flash("error_msg", message);
  return res.redirect(options.redirectTo || "/admin/about-us");
};

/**
 * GET /api/about
 * Lấy dữ liệu About Us (Public API cho website và CMS load dữ liệu)
 */
exports.getAbout = async (req, res) => {
  try {
    // Force no-cache headers
    res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
    res.setHeader("Pragma", "no-cache");
    res.setHeader("Expires", "0");

    const data = await AboutUs.getSingle();
    const rawData = buildCanonicalAboutData(data.toObject());

    // === Dynamic Blog News Section ===
    const news = rawData.news || {};
    const selectedBlogIds = Array.isArray(news.selectedBlogIds)
      ? news.selectedBlogIds.map((id) => id.toString())
      : [];
    const selectedObjectIds = selectedBlogIds
      .map((id) => toObjectId(id))
      .filter(Boolean);
    let blogs = [];

    // Nếu có chọn blog cụ thể
    if (selectedBlogIds.length > 0) {
      const selectedQuery = await Blog.find({
        _id: { $in: selectedObjectIds },
        status: "published",
      }).lean();

      // Sắp xếp theo thứ tự đã chọn trong selectedBlogIds
      selectedQuery.sort((a, b) => {
        return (
          selectedBlogIds.indexOf(a._id.toString()) -
          selectedBlogIds.indexOf(b._id.toString())
        );
      });

      blogs = selectedQuery.slice(0, 3);

      if (blogs.length < 3) {
        const missingCount = 3 - blogs.length;
        const extraBlogs = await Blog.find({
          status: "published",
          _id: {
            $nin: [...blogs.map((blog) => blog._id), ...selectedObjectIds],
          },
        })
          .sort({ createdAt: -1 })
          .limit(missingCount)
          .lean();

        blogs = [...blogs, ...extraBlogs];
      }
    }

    // Nếu không chọn hoặc chọn nhưng không đủ, lấy thêm 3 bài mới nhất
    if (blogs.length === 0) {
      blogs = await Blog.find({ status: "published" })
        .sort({ createdAt: -1 })
        .limit(3)
        .lean();
    }

    // Map dữ liệu blog sang format mà frontend mong đợi
    news.items = blogs.slice(0, 3).map((blog, index) => resolveNewsItem(blog, index));

    rawData.news = news;
    // ===============================

    const baseUrl =
      process.env.BACKEND_URL || `${req.protocol}://${req.get("host")}`;
    const processedData = addBaseUrlToImages(rawData, baseUrl);

    res.json(processedData);
  } catch (error) {
    console.error("Error getting about data:", error);
    res.status(500).json({
      success: false,
      error: "Failed to get about data",
    });
  }
};

/**
 * PUT /api/about
 * Cập nhật dữ liệu About Us (Dùng cho AJAX từ CMS)
 */
exports.updateAbout = async (req, res) => {
  try {
    let updateData = req.body;

    // Nếu dữ liệu gửi qua trường aboutJson (dạng string JSON)
    if (updateData.aboutJson && typeof updateData.aboutJson === "string") {
      try {
        updateData = JSON.parse(updateData.aboutJson);
      } catch (e) {
        return res.status(400).json({
          success: false,
          message: "Invalid JSON in aboutJson",
        });
      }
    }

    const doc = await AboutUs.getSingle();

    // ✅ Capture BEFORE state
    const beforeData = JSON.parse(JSON.stringify(doc.toObject()));

    updateData = buildCanonicalAboutData(updateData);

    const validation = validateLengthRules(updateData, ABOUT_US_LENGTH_RULES);
    if (!validation.valid) {
      return handleLengthValidation(validation, req, res, { json: true });
    }

    // Use .set() for better handling of nested objects/arrays in Mongoose
    doc.set(updateData);
    await doc.save();

    // ✅ Capture AFTER state
    const afterData = JSON.parse(JSON.stringify(doc.toObject()));

    // ✅ AUDIT LOGGING - About Us Updated
    const changes = diffObject(beforeData, afterData);
    if (changes.length > 0) {
      await writeAuditLog({
        model: "AboutUs",
        documentId: doc._id,
        action: AUDIT_ACTIONS.UPDATE_ABOUT_US,
        before: beforeData,
        after: afterData,
        changes,
        req,
      });
      console.log(
        `✅ Audit log created for About Us update: ${changes.length} changes`,
      );
    } else {
      console.log("ℹ️ No changes detected for About Us update");
    }

    // Fetch fresh data for syncing and returning
    const finalData = buildCanonicalAboutData(
      await AboutUs.findOne()
      .select("-_id -__v -createdAt -updatedAt")
      .lean(),
    );

    // Update about.json file to keep it in sync
    jsonHelper.writeJsonFile("about", finalData);

    res.json({
      success: true,
      message: "About page updated successfully",
      data: finalData,
    });
  } catch (error) {
    console.error("Error updating about data:", error);
    res.status(500).json({
      success: false,
      error: "Failed to update about data: " + error.message,
    });
  }
};

/**
 * Render admin page (Dùng cho Admin UI)
 */
exports.index = async (req, res) => {
  try {
    const data = await AboutUs.getSingle();
    const rawData = buildCanonicalAboutData(data.toObject());

    // Lấy tất cả blog để chọn trong CMS
    const allBlogs = await Blog.find({ status: "published" })
      .sort({ createdAt: -1 })
      .lean();

    const activeTab = req.query.activeTab || "hero";
    res.render("admin/aboutUs/index", {
      layout: "layouts/main",
      title: "About Page Management",
      data: rawData,
      allBlogs,
      activeTab,
      user: req.session.user,
      currentPath: req.path,
      frontendUrl: process.env.FRONTEND_URL || "http://localhost:3000",
      backendUrl: process.env.BACKEND_URL || "http://localhost:3001",
    });
  } catch (err) {
    console.error("Error in about index:", err);
    req.flash("error_msg", "Error loading About page");
    res.redirect("/admin/dashboard");
  }
};

/**
 * Update method cho form-based submission (Admin UI - Post fallback)
 */
exports.update = async (req, res) => {
  try {
    let updateData = req.body;
    if (updateData.aboutJson && typeof updateData.aboutJson === "string") {
      try {
        updateData = JSON.parse(updateData.aboutJson);
      } catch (e) {
        req.flash("error_msg", "Invalid JSON data");
        return res.redirect("/admin/about-us");
      }
    }

    const doc = await AboutUs.getSingle();
    updateData = buildCanonicalAboutData(updateData);

    // ✅ Capture BEFORE state
    const beforeData = JSON.parse(JSON.stringify(doc.toObject()));

    const validation = validateLengthRules(updateData, ABOUT_US_LENGTH_RULES);
    if (!validation.valid) {
      return handleLengthValidation(validation, req, res, {
        redirectTo: `/admin/about-us?activeTab=${req.query.activeTab || "hero"}`,
      });
    }

    doc.set(updateData);
    await doc.save();

    // ✅ Capture AFTER state
    const afterData = JSON.parse(JSON.stringify(doc.toObject()));

    // ✅ AUDIT LOGGING - About Us Updated
    const changes = diffObject(beforeData, afterData);
    if (changes.length > 0) {
      await writeAuditLog({
        model: "AboutUs",
        documentId: doc._id,
        action: AUDIT_ACTIONS.UPDATE_ABOUT_US,
        before: beforeData,
        after: afterData,
        changes,
        req,
      });
    }

    const finalData = buildCanonicalAboutData(
      await AboutUs.findOne()
      .select("-_id -__v -createdAt -updatedAt")
      .lean(),
    );
    jsonHelper.writeJsonFile("about", finalData);

    req.flash("success_msg", "About page updated successfully");
    const activeTab = req.query.activeTab || "hero";
    res.redirect(`/admin/about-us?activeTab=${activeTab}`);
  } catch (err) {
    console.error("Update error:", err);
    req.flash("error_msg", "Error updating About page: " + err.message);
    res.redirect("/admin/about-us");
  }
};

// Aliases for compatibility
exports.api = exports.getAbout;
exports.page = exports.getAbout;
exports.updateAboutUs = exports.updateAbout;
