const express = require("express");
const Post = require("../models/Post");
const couchdbService = require("../services/couchdbService");
const auth = require("../middleware/auth");
const { asyncHandler } = require("../middleware/errorHandler");
const {
  createPostValidation,
  postIdValidation,
} = require("../middleware/validators/postValidator");
const { upload, handleUploadError } = require("../middleware/upload");
const { uploadImage, deleteImage } = require("../config/cloudinary");
const { paginate, buildPaginatedResponse } = require("../middleware/pagination");
const { getCacheMiddleware, invalidateCacheByPattern } = require("../middleware/cache");

const router = express.Router();

// Get all posts (with pagination)
router.get(
  "/",
  paginate,
  getCacheMiddleware(60), // Cache for 1 minute
  asyncHandler(async (req, res) => {
    const { skip, limit, page } = req.pagination;

    const posts = await Post.findAll({ skip, limit });

    const totalCount = await Post.countDocuments();

    res.json(buildPaginatedResponse(posts, totalCount, page, limit));
  }),
);

// Create a post with optional image
router.post(
  "/",
  auth,
  upload.single("image"),
  handleUploadError,
  asyncHandler(async (req, res) => {
    const { content } = req.body;

    if (!content) {
      return res.status(400).json({ msg: "Content is required" });
    }

    const postData = {
      user: req.user.id,
      content,
    };

    // Upload image if provided
    if (req.file) {
      const result = await uploadImage(
        req.file.buffer,
        "adopt-a-street/posts",
      );
      postData.imageUrl = result.url;
      postData.cloudinaryPublicId = result.publicId;
    }

    const post = await Post.create(postData);

    // Invalidate posts cache
    invalidateCacheByPattern('/api/posts');

    // Emit SSE event for new post
    const sse = req.app.get("sse");
    if (sse) {
      sse.broadcastToTopic("posts", "newPost", {
        post,
      });
    }

    res.json({
      post,
      pointsAwarded: 5, // Standard post creation points
      newBalance: 0, // Will be updated by couchdbService
      badgesEarned: [], // Will be handled by couchdbService
    });
  }),
);

// Add image to existing post
router.post(
  "/:id/image",
  auth,
  upload.single("image"),
  handleUploadError,
  postIdValidation,
  asyncHandler(async (req, res) => {
    const post = await Post.findById(req.params.id);
    if (!post) {
      return res.status(404).json({ msg: "Post not found" });
    }

    // Verify user owns the post
    if (post.user.userId !== req.user.id) {
      return res.status(403).json({ msg: "Not authorized" });
    }

    if (!req.file) {
      return res.status(400).json({ msg: "No image file provided" });
    }

    // Delete old image if exists
    if (post.cloudinaryPublicId) {
      await deleteImage(post.cloudinaryPublicId);
    }

    // Upload new image
    const result = await uploadImage(
      req.file.buffer,
      "adopt-a-street/posts",
    );

    const updatedPost = await Post.updatePost(req.params.id, {
      imageUrl: result.url,
      cloudinaryPublicId: result.publicId,
    });

    res.json(updatedPost);
  }),
);

// Like a post
router.put(
  "/like/:id",
  auth,
  postIdValidation,
  asyncHandler(async (req, res) => {
    const post = await Post.findById(req.params.id);
    if (!post) {
      return res.status(404).json({ msg: "Post not found" });
    }

    // Check if the post has already been liked by this user
    if (post.likes.includes(req.user.id)) {
      return res.status(400).json({ msg: "Post already liked" });
    }

    const updatedPost = await Post.addLike(req.params.id, req.user.id);

    // Emit SSE event for post like
    const sse = req.app.get("sse");
    if (sse) {
      sse.broadcastToTopic("posts", "postUpdate", {
        type: "post_liked",
        postId: req.params.id,
        likes: updatedPost.likes,
      });
    }

    res.json(updatedPost.likes);
  }),
);

// Unlike a post
router.put(
  "/unlike/:id",
  auth,
  postIdValidation,
  asyncHandler(async (req, res) => {
    const post = await Post.findById(req.params.id);
    if (!post) {
      return res.status(404).json({ msg: "Post not found" });
    }

    // Check if the post has been liked by this user
    if (!post.likes.includes(req.user.id)) {
      return res.status(400).json({ msg: "Post not yet liked" });
    }

    const updatedPost = await Post.removeLike(req.params.id, req.user.id);

    res.json(updatedPost.likes);
  }),
);

module.exports = router;
