const Blog = require('../models/blog');
const BlogCategory = require('../models/blogCategory');
const BlogTag = require('../models/blogTag');
const BlogComment = require('../models/blogComment');
const RecentPost = require('../models/recentPost');
const { addBaseUrlToImages, getFullImageUrl } = require('../utils/imageHelper');
const slugify = require('slugify');

// -------------------- Helper Functions --------------------

// Generate slug from title
const generateSlug = (title) => {
  return slugify(title, {
    lower: true,
    strict: true,
    locale: 'vi'
  });
};

// Update category post counts
const updateCategoryPostCounts = async () => {
  const categories = await BlogCategory.find();
  for (const category of categories) {
    await category.updatePostCount();
  }
};

// Update tag post counts
const updateTagPostCounts = async () => {
  const tags = await BlogTag.find();
  for (const tag of tags) {
    await tag.updatePostCount();
  }
};

// -------------------- Admin Controllers --------------------

// Display blog management page
exports.index = async (req, res) => {
  try {
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 10;
    const skip = (page - 1) * limit;
    
    // Build filter
    const filter = {};
    if (req.query.status) {
      filter.status = req.query.status;
    }
    if (req.query.category) {
      filter.category = req.query.category;
    }
    if (req.query.search) {
      filter.$or = [
        { title: { $regex: req.query.search, $options: 'i' } },
        { excerpt: { $regex: req.query.search, $options: 'i' } }
      ];
    }
    
    // Get blogs with pagination
    const blogs = await Blog.find(filter)
      .sort({ createdAt: -1 })
      .skip(skip)
      .limit(limit)
      .lean();
    
    const totalBlogs = await Blog.countDocuments(filter);
    const totalPages = Math.ceil(totalBlogs / limit);
    
    // Get categories for filter
    const categories = await BlogCategory.getActive();

    const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:3000';
    const backendUrl = process.env.BACKEND_URL || 'http://localhost:3001';
    
    res.render('admin/blog/index', {
      layout: 'layouts/main',
      title: 'Blog Management',
      blogs,
      categories,
      frontendUrl,
      backendUrl,
      getFullImageUrl, // Truyền helper function vào template
      pagination: {
        current: page,
        total: totalPages,
        limit,
        totalItems: totalBlogs
      },
      query: req.query,
      currentPath: req.path,
      user: req.session.user
    });
  } catch (err) {
    console.error('Blog index error:', err);
    req.flash('error_msg', 'Error loading blogs');
    res.redirect('/admin/dashboard');
  }
};

// Show create blog form
exports.create = async (req, res) => {
  try {
    const categories = await BlogCategory.getActive();
    const tags = await BlogTag.getActive();
    
    const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:3000';
    const backendUrl = process.env.BACKEND_URL || 'http://localhost:3001';
    
    res.render('admin/blog/create', {
      layout: 'layouts/main',
      title: 'Create New Blog Post',
      categories,
      tags,
      currentPath: req.path,
      user: req.session.user,
      frontendUrl,
      backendUrl,
      getFullImageUrl // Truyền helper function vào template
    });
  } catch (err) {
    console.error('Blog create form error:', err);
    req.flash('error_msg', 'Error loading create form');
    res.redirect('/admin/blog');
  }
};

// Store new blog
exports.store = async (req, res) => {
  try {
    const {
      title,
      excerpt,
      content,
      category,
      tags,
      status,
      isFeatured,
      author,
      galleryImages,
      quote,
      contentAfterQuote
    } = req.body;
    
    // Generate slug
    const slug = generateSlug(title);
    
    // Check if slug exists
    const existingBlog = await Blog.findOne({ slug });
    if (existingBlog) {
      req.flash('error_msg', 'A blog post with this title already exists');
      return res.redirect('/admin/blog/create');
    }
    
    // Create blog data
    const blogData = {
      title,
      slug,
      excerpt,
      content,
      category: category ? (Array.isArray(category) ? category : [category]) : [], // Array categories
      tags: tags ? (Array.isArray(tags) ? tags : [tags]) : [],
      status: status || 'published',
      isFeatured: isFeatured === 'on',
      author: author || 'Admin',
      galleryImages: galleryImages ? (Array.isArray(galleryImages) ? galleryImages : [galleryImages]) : [],
      quote: quote || '',
      contentAfterQuote: contentAfterQuote || ''
    };
    
    // Handle featured image - using featuredImageUrl from form (uploaded via AJAX)
    if (req.body.featuredImageUrl) {
      blogData.featuredImage = req.body.featuredImageUrl;
    }
    
    // Create blog
    const blog = new Blog(blogData);
    await blog.save();
    
    // Update counts
    await updateCategoryPostCounts();
    await updateTagPostCounts();
    await RecentPost.syncFromBlogs();
    
    req.flash('success_msg', 'Blog post created successfully');
    res.redirect('/admin/blog');
  } catch (err) {
    console.error('Blog store error:', err);
    req.flash('error_msg', 'Error creating blog post');
    res.redirect('/admin/blog/create');
  }
};

// Show edit blog form
exports.edit = async (req, res) => {
  try {
    const blog = await Blog.findById(req.params.id);
    
    if (!blog) {
      req.flash('error_msg', 'Blog post not found');
      return res.redirect('/admin/blog');
    }
    
    const categories = await BlogCategory.getActive();
    const tags = await BlogTag.getActive();
    
    // Get all comments for this blog post (including pending, approved, rejected)
    const allComments = await BlogComment.find({ postId: blog._id })
      .sort({ createdAt: -1 })
      .lean();
    
    // Organize comments with replies
    const parentComments = allComments.filter(c => !c.parentId);
    const commentsWithReplies = parentComments.map(parent => {
      const replies = allComments.filter(c => c.parentId && c.parentId.toString() === parent._id.toString());
      return {
        ...parent,
        replies: replies
      };
    });
    
    const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:3000';
    const backendUrl = process.env.BACKEND_URL || 'http://localhost:3001';
    
    res.render('admin/blog/edit', {
      layout: 'layouts/main',
      title: 'Edit Blog Post',
      blog,
      categories,
      tags,
      comments: commentsWithReplies,
      commentsCount: allComments.length,
      currentPath: req.path,
      user: req.session.user,
      frontendUrl,
      backendUrl,
      getFullImageUrl // Truyền helper function vào template
    });
  } catch (err) {
    console.error('Blog edit form error:', err);
    req.flash('error_msg', 'Error loading blog post');
    res.redirect('/admin/blog');
  }
};

// Update blog
exports.update = async (req, res) => {
  try {
    const blog = await Blog.findById(req.params.id);
    
    if (!blog) {
      req.flash('error_msg', 'Blog post not found');
      return res.redirect('/admin/blog');
    }
    
    const {
      title,
      excerpt,
      content,
      category,
      tags,
      status,
      isFeatured,
      author,
      galleryImages,
      quote,
      contentAfterQuote
    } = req.body;
    
    // Update blog data
    blog.title = title;
    blog.excerpt = excerpt;
    blog.content = content;
    blog.category = category ? (Array.isArray(category) ? category : [category]) : []; // Array categories
    blog.tags = tags ? (Array.isArray(tags) ? tags : [tags]) : [];
    blog.status = status || 'published';
    blog.isFeatured = isFeatured === 'on';
    blog.author = author || 'Admin';
    blog.galleryImages = galleryImages ? (Array.isArray(galleryImages) ? galleryImages : [galleryImages]) : [];
    blog.quote = quote || '';
    blog.contentAfterQuote = contentAfterQuote || '';
    
    // Handle featured image - using featuredImageUrl from form (uploaded via AJAX)
    if (req.body.featuredImageUrl) {
      blog.featuredImage = req.body.featuredImageUrl;
    }
    
    // Generate new slug if title changed
    const newSlug = generateSlug(title);
    if (newSlug !== blog.slug) {
      const existingBlog = await Blog.findOne({ slug: newSlug, _id: { $ne: blog._id } });
      if (existingBlog) {
        req.flash('error_msg', 'A blog post with this title already exists');
        return res.redirect(`/admin/blog/${blog._id}/edit`);
      }
      blog.slug = newSlug;
    }
    
    await blog.save();
    
    // Update counts
    await updateCategoryPostCounts();
    await updateTagPostCounts();
    await RecentPost.syncFromBlogs();
    
    req.flash('success_msg', 'Blog post updated successfully');
    res.redirect('/admin/blog');
  } catch (err) {
    console.error('Blog update error:', err);
    req.flash('error_msg', 'Error updating blog post');
    res.redirect(`/admin/blog/${req.params.id}/edit`);
  }
};

// Delete blog
exports.destroy = async (req, res) => {
  try {
    const blog = await Blog.findById(req.params.id);
    
    if (!blog) {
      req.flash('error_msg', 'Blog post not found');
      return res.redirect('/admin/blog');
    }
    
    await Blog.findByIdAndDelete(req.params.id);
    
    // Update counts
    await updateCategoryPostCounts();
    await updateTagPostCounts();
    await RecentPost.syncFromBlogs();
    
    req.flash('success_msg', 'Blog post deleted successfully');
    res.redirect('/admin/blog');
  } catch (err) {
    console.error('Blog delete error:', err);
    req.flash('error_msg', 'Error deleting blog post');
    res.redirect('/admin/blog');
  }
};

// -------------------- Public API Controllers --------------------

// Get all published blogs for frontend
exports.api = async (req, res) => {
  try {
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 10;
    const skip = (page - 1) * limit;
    
    // Build filter
    const filter = { status: 'published' };
    
    if (req.query.category) {
      filter.category = { $in: [req.query.category] }; // Tìm trong array categories
    }
    
    if (req.query.tag) {
      filter.tags = { $in: [req.query.tag] }; // Tìm trong array tags
    }
    
    if (req.query.search) {
      filter.$or = [
        { title: { $regex: req.query.search, $options: 'i' } },
        { excerpt: { $regex: req.query.search, $options: 'i' } }
      ];
    }
    
    // Get blogs
    const blogs = await Blog.find(filter)
      .sort({ createdAt: -1 })
      .skip(skip)
      .limit(limit)
      .lean();
    
    const totalBlogs = await Blog.countDocuments(filter);
    
    // Add base URL to images
    const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
    const processedBlogs = blogs.map(blog => addBaseUrlToImages(blog, baseUrl));
    
    res.json({
      success: true,
      message: 'Blogs fetched successfully',
      data: {
        blogs: processedBlogs,
        pagination: {
          current: page,
          total: Math.ceil(totalBlogs / limit),
          limit,
          totalItems: totalBlogs
        }
      }
    });
  } catch (err) {
    console.error('Blog API error:', err);
    res.status(500).json({
      success: false,
      message: 'Error loading blogs',
      error: err.message || 'Error loading blogs'
    });
  }
};

// Get single blog by slug
exports.apiShow = async (req, res) => {
  try {
    const blog = await Blog.findOne({ 
      slug: req.params.slug, 
      status: 'published' 
    }).lean();
    
    if (!blog) {
      return res.status(404).json({
        success: false,
        message: 'Blog post not found'
      });
    }
    
    // Get comments for this post (parent comments only)
    const parentComments = await BlogComment.getApprovedByPost(blog._id);
    
    // Get replies for each parent comment
    const commentsWithReplies = await Promise.all(
      parentComments.map(async (parentComment) => {
        const replies = await BlogComment.getReplies(parentComment._id);
        return {
          ...parentComment.toObject(),
          replies: replies.map(reply => reply.toObject())
        };
      })
    );
    
    // Flatten comments array (parent + replies)
    const allComments = commentsWithReplies.flatMap(comment => [
      comment,
      ...comment.replies
    ]);
    
    // Add comments to blog
    blog.comments = allComments;
    // Keep commentsCount in sync for frontend
    blog.commentsCount = allComments.length;
    
    // Add base URL to images
    const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
    const processedBlog = addBaseUrlToImages(blog, baseUrl);
    
    res.json({
      success: true,
      message: 'Blog post fetched successfully',
      data: processedBlog
    });
  } catch (err) {
    console.error('Blog show API error:', err);
    res.status(500).json({
      success: false,
      message: 'Error loading blog post',
      error: err.message || 'Error loading blog post'
    });
  }
};

// Create a comment (no moderation for now: default approved)
exports.apiCreateComment = async (req, res) => {
  try {
    const { authorName, authorEmail, authorPhone, authorAddress, authorDate, content, parentId } = req.body || {};

    if (!authorName || !String(authorName).trim()) {
      return res.status(400).json({
        success: false,
        message: "authorName is required",
      });
    }

    if (!content || !String(content).trim()) {
      return res.status(400).json({
        success: false,
        message: "content is required",
      });
    }

    const blog = await Blog.findOne({ slug: req.params.slug, status: "published" }).lean();
    if (!blog) {
      return res.status(404).json({
        success: false,
        message: "Blog post not found",
      });
    }

    // If replying, ensure parent exists and belongs to same post
    let parentObjectId = null;
    if (parentId) {
      const parent = await BlogComment.findOne({ _id: parentId, postId: blog._id }).lean();
      if (!parent) {
        return res.status(400).json({
          success: false,
          message: "Invalid parentId",
        });
      }
      parentObjectId = parentId;
    }

    const newComment = await BlogComment.create({
      postId: blog._id,
      authorName: String(authorName).trim(),
      ...(authorEmail ? { authorEmail: String(authorEmail).trim() } : {}),
      ...(authorPhone ? { authorPhone: String(authorPhone).trim() } : {}),
      ...(authorAddress ? { authorAddress: String(authorAddress).trim() } : {}),
      ...(authorDate ? { authorDate: String(authorDate).trim() } : {}),
      content: String(content).trim(),
      parentId: parentObjectId,
      status: "approved",
    });

    // Keep counter roughly correct (also counts replies)
    await Blog.updateOne({ _id: blog._id }, { $inc: { commentsCount: 1 } });

    return res.json({
      success: true,
      message: "Comment created successfully",
      data: newComment.toJSON(),
    });
  } catch (err) {
    console.error("Create comment API error:", err);
    return res.status(500).json({
      success: false,
      message: "Error creating comment",
      error: err.message || "Error creating comment",
    });
  }
};

// Get featured blogs
exports.apiFeatured = async (req, res) => {
  try {
    const limit = parseInt(req.query.limit) || 3;
    
    const blogs = await Blog.getFeatured()
      .limit(limit)
      .lean();
    
    // Add base URL to images
    const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('port')}`;
    const processedBlogs = blogs.map(blog => addBaseUrlToImages(blog, baseUrl));
    
    res.json({
      success: true,
      message: 'Featured blogs fetched successfully',
      data: processedBlogs
    });
  } catch (err) {
    console.error('Featured blogs API error:', err);
    res.status(500).json({
      success: false,
      message: 'Error loading featured blogs',
      error: err.message || 'Error loading featured blogs'
    });
  }
};

// Get recent blogs
exports.apiRecent = async (req, res) => {
  try {
    const limit = parseInt(req.query.limit) || 5;
    
    // Try to get from RecentPost first
    let recentPosts = await RecentPost.getRecent(limit);
    
    // If no recent posts, sync from blogs
    if (recentPosts.length === 0) {
      await RecentPost.syncFromBlogs(limit);
      recentPosts = await RecentPost.getRecent(limit);
    }
    
    // Add base URL to images
    const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get('host')}`;
    const processedPosts = recentPosts.map(post => addBaseUrlToImages(post, baseUrl));
    
    res.json({
      success: true,
      message: 'Recent blogs fetched successfully',
      data: processedPosts
    });
  } catch (err) {
    console.error('Recent blogs API error:', err);
    res.status(500).json({
      success: false,
      message: 'Error loading recent blogs',
      error: err.message || 'Error loading recent blogs'
    });
  }
};

// Get categories of a specific blog post
exports.apiCategories = async (req, res) => {
  try {
    const mongoose = require('mongoose');
    let query;
    
    // Check if it's a valid ObjectId
    if (mongoose.Types.ObjectId.isValid(req.params.id)) {
      query = { _id: req.params.id };
    } else {
      query = { slug: req.params.id };
    }
    
    query.status = 'published';
    
    const blog = await Blog.findOne(query).lean();
    
    if (!blog) {
      return res.status(404).json({
        success: false,
        message: 'Blog post not found'
      });
    }
    
    // Get category details
    const BlogCategory = require('../models/blogCategory');
    const categories = await BlogCategory.find({ 
      name: { $in: blog.category },
      isActive: true 
    }).lean();
    
    res.json({
      success: true,
      message: 'Blog categories fetched successfully',
      data: categories
    });
  } catch (err) {
    console.error('Blog categories API error:', err);
    res.status(500).json({
      success: false,
      message: 'Error loading blog categories',
      error: err.message || 'Error loading blog categories'
    });
  }
};

// Get tags of a specific blog post
exports.apiTags = async (req, res) => {
  try {
    const mongoose = require('mongoose');
    let query;
    
    // Check if it's a valid ObjectId
    if (mongoose.Types.ObjectId.isValid(req.params.id)) {
      query = { _id: req.params.id };
    } else {
      query = { slug: req.params.id };
    }
    
    query.status = 'published';
    
    const blog = await Blog.findOne(query).lean();
    
    if (!blog) {
      return res.status(404).json({
        success: false,
        message: 'Blog post not found'
      });
    }
    
    // Get tag details
    const BlogTag = require('../models/blogTag');
    const tags = await BlogTag.find({ 
      name: { $in: blog.tags },
      isActive: true 
    }).lean();
    
    res.json({
      success: true,
      message: 'Blog tags fetched successfully',
      data: tags
    });
  } catch (err) {
    console.error('Blog tags API error:', err);
    res.status(500).json({
      success: false,
      message: 'Error loading blog tags',
      error: err.message || 'Error loading blog tags'
    });
  }
};

// -------------------- Comment Management Controllers --------------------

// Approve a comment
exports.approveComment = async (req, res) => {
  try {
    const { blogId, commentId } = req.params;
    
    const blog = await Blog.findById(blogId);
    if (!blog) {
      return res.status(404).json({
        success: false,
        message: 'Blog post not found'
      });
    }
    
    const comment = await BlogComment.findById(commentId);
    if (!comment || comment.postId.toString() !== blogId) {
      return res.status(404).json({
        success: false,
        message: 'Comment not found'
      });
    }
    
    comment.status = 'approved';
    await comment.save();
    
    res.json({
      success: true,
      message: 'Comment approved successfully'
    });
  } catch (err) {
    console.error('Approve comment error:', err);
    res.status(500).json({
      success: false,
      message: 'Error approving comment',
      error: err.message || 'Error approving comment'
    });
  }
};

// Reject a comment
exports.rejectComment = async (req, res) => {
  try {
    const { blogId, commentId } = req.params;
    
    const blog = await Blog.findById(blogId);
    if (!blog) {
      return res.status(404).json({
        success: false,
        message: 'Blog post not found'
      });
    }
    
    const comment = await BlogComment.findById(commentId);
    if (!comment || comment.postId.toString() !== blogId) {
      return res.status(404).json({
        success: false,
        message: 'Comment not found'
      });
    }
    
    comment.status = 'rejected';
    await comment.save();
    
    res.json({
      success: true,
      message: 'Comment rejected successfully'
    });
  } catch (err) {
    console.error('Reject comment error:', err);
    res.status(500).json({
      success: false,
      message: 'Error rejecting comment',
      error: err.message || 'Error rejecting comment'
    });
  }
};

// Delete a comment
exports.deleteComment = async (req, res) => {
  try {
    const { blogId, commentId } = req.params;
    
    const blog = await Blog.findById(blogId);
    if (!blog) {
      return res.status(404).json({
        success: false,
        message: 'Blog post not found'
      });
    }
    
    const comment = await BlogComment.findById(commentId);
    if (!comment || comment.postId.toString() !== blogId) {
      return res.status(404).json({
        success: false,
        message: 'Comment not found'
      });
    }
    
    // Delete the comment and all its replies
    await BlogComment.deleteMany({
      $or: [
        { _id: commentId },
        { parentId: commentId }
      ]
    });
    
    // Update blog comment count
    const remainingComments = await BlogComment.countDocuments({ postId: blogId });
    await Blog.updateOne({ _id: blogId }, { commentsCount: remainingComments });
    
    res.json({
      success: true,
      message: 'Comment deleted successfully'
    });
  } catch (err) {
    console.error('Delete comment error:', err);
    res.status(500).json({
      success: false,
      message: 'Error deleting comment',
      error: err.message || 'Error deleting comment'
    });
  }
};

module.exports = exports;