const db = require("../../db");
const path = require("path");
const fs = require("fs");

const categories = require("../../models/Blog/categories");

const UPLOAD_DIR = path.join(__dirname, "../public/uploads/blogs");
if (!fs.existsSync(UPLOAD_DIR)) {
  fs.mkdirSync(UPLOAD_DIR, { recursive: true });
}

// Helper function to generate unique URL
const generateUniqueUrl = (title) => {
  return (
    title
      .toLowerCase()
      .replace(/\s+/g, "-")
      .replace(/[^\w-]+/g, "") +
    "-" +
    Date.now()
  );
};

exports.createBlog = async (req, res) => {
  try {
    // Validate required fields
    const requiredFields = ["title", "author", "description", "category"];
    const missingFields = requiredFields.filter((field) => !req.body[field]);

    if (missingFields.length > 0) {
      return res.status(400).json({
        error: "Missing required fields",
        missingFields,
      });
    }

    // Validate category
    if (!categories.includes(req.body.category)) {
      return res.status(400).json({
        error: "Invalid category",
        allowedCategories: categories,
      });
    }

    // Handle file upload
    let featuredImagePath = "";
    if (req.files?.featuredImage) {
      const file = req.files.featuredImage;
      const fileName = `${Date.now()}-${file.name.replace(/\s+/g, "-")}`;
      const filePath = path.join(UPLOAD_DIR, fileName);

      await file.mv(filePath);
      featuredImagePath = `/uploads/blogs/${fileName}`;
    }

    // Generate URL if not provided
    const url = req.body.url || generateUniqueUrl(req.body.title);

    // Check if URL already exists
    const existingBlog = await db.Blog.findOne({ where: { url } });
    if (existingBlog) {
      return res.status(400).json({
        error: "URL already exists",
        suggestion:
          "Please provide a different URL or leave it blank to auto-generate",
      });
    }

    const blogData = {
      title: req.body.title,
      author: req.body.author,
      description: req.body.description,
      category: req.body.category,
      tags: req.body.tags || "",
      metaKeywords: req.body.metaKeywords || "",
      metaDescription: req.body.metaDescription || "",
      altTag: req.body.altTag || "",
      url: url,
      status: req.body.status || "draft",
      featuredImage: featuredImagePath,
    };

    const blog = await db.Blog.create(blogData);

    res.status(201).json({
      success: true,
      message: "Blog created successfully",
      blog,
    });
  } catch (err) {
    console.error("Error:", err);

    // Handle validation errors
    if (err.name === "SequelizeValidationError") {
      const errors = err.errors.map((e) => e.message);
      return res.status(400).json({
        success: false,
        message: "Validation errors",
        errors,
      });
    }

    // Handle unique constraint errors
    if (err.name === "SequelizeUniqueConstraintError") {
      return res.status(400).json({
        success: false,
        message: "Unique constraint violation",
        error: err.errors[0].message,
      });
    }

    res.status(500).json({
      success: false,
      message: "Failed to create blog",
      error: process.env.NODE_ENV === "development" ? err.message : undefined,
    });
  }
};

exports.getBlog = async (req, res) => {
  try {
    const { id } = req.query;

    if (id) {
      const blog = await db.Blog.findByPk(id);
      if (!blog) {
        return res.status(404).json({ error: "Blog not found" });
      }
      return res.json(blog);
    }

    // Get all blogs with optional filters
    const where = {};
    if (req.query.category) {
      where.category = req.query.category;
    }
    if (req.query.status) {
      where.status = req.query.status;
    }

    const blogs = await db.Blog.findAll({
      where,
      order: [["createdAt", "DESC"]],
    });

    res.json(blogs);
  } catch (err) {
    console.error("Error fetching blog(s):", err);
    res.status(500).json({ error: "Failed to fetch blog(s)" });
  }
};

exports.getCategories = async (req, res) => {
  try {
    res.json(categories);
  } catch (err) {
    res.status(500).json({ error: "Failed to fetch categories" });
  }
};

exports.putBlog = async (req, res) => {
  try {
    const blogId = req.params.id;
    const blog = await db.Blog.findByPk(blogId);

    if (!blog) {
      return res.status(404).json({
        status: false,
        message: "Blog not found",
      });
    }

    // Check if URL is being updated and if it's unique
    if (req.body.url && req.body.url !== blog.url) {
      const existingBlog = await db.Blog.findOne({
        where: { url: req.body.url },
      });
      if (existingBlog) {
        return res.status(400).json({
          status: false,
          message: "The new URL already exists. Please use a different URL.",
        });
      }
    }

    // Update only allowed fields
    const updatableFields = [
      "title",
      "author",
      "description",
      "category",
      "tags",
      "metaKeywords",
      "metaDescription",
      "altTag",
      "url",
      "status",
      "featuredImage",
    ];

    updatableFields.forEach((field) => {
      if (req.body[field] !== undefined) {
        blog[field] = req.body[field];
      }
    });

    await blog.save();

    return res.status(200).json({
      status: true,
      message: "Blog updated successfully",
      data: blog,
    });
  } catch (error) {
    console.error("Update error:", error);

    if (error.name === "SequelizeUniqueConstraintError") {
      return res.status(400).json({
        status: false,
        message: "URL must be unique",
        error: "The provided URL already exists in the system",
      });
    }

    return res.status(500).json({
      status: false,
      message: "Failed to update blog",
      error: error.message,
    });
  }
};

exports.deleteBlog = async (req, res) => {
  try {
    const blogId = req.params.id;

    if (!blogId) {
      return res.status(400).json({
        status: false,
        message: "Blog id is required",
      });
    }

    const blog = await db.Blog.findByPk(blogId);
    if (!blog) {
      return res.status(404).json({
        status: false,
        message: "Blog not found",
      });
    }

    await blog.destroy();

    return res.status(200).json({
      status: true,
      message: "Blog deleted successfully",
    });
  } catch (error) {
    console.error("Delete error:", error);
    return res.status(500).json({
      status: false,
      message: "Failed to delete blog",
      error: error.message,
    });
  }
};
