const { QueryTypes } = require('sequelize');
const { CustomerReviews, Users, sequelize, Bookings } = require('../../models');
const { paginate } = require('../../util/pagination');
const { formatTimestamp } = require('../../util');
const { checkManagerAccess } = require('../../helpers/managers');

exports.createReview = async (req, res, next) => {
  try {
    const { customerId } = req.params;

    let hostId = req.userId;
    if (req.query.hostId) {
      hostId = (await checkManagerAccess(req, 'Reviews')).hostId;
    }
    const host = await Users.findByPk(hostId);

    if (!host) {
      return res.status(404).json({
        success: false,
        message: 'Host not found',
      });
    }

    if (!host.is_host) {
      return res.status(403).json({
        success: false,
        message: 'You are not authorized to review this customer',
      });
    }

    const hasValidBooking = await sequelize.query(
      `SELECT 
    			COUNT(*) as count
			FROM 
    			bookings 
			WHERE 
    			host_id = ?
    		AND customer_id = ?
    		AND status IN ('Done', 'Cancelled')`,
      {
        type: QueryTypes.SELECT,
        replacements: [hostId, customerId],
      },
    );

    if (!hasValidBooking[0].count) {
      return res.status(403).json({
        success: false,
        message: 'You are not authorized to review this customer, no valid booking found',
      });
    }

    await CustomerReviews.create({
      content: req.body.content,
      rating: req.body.rating,
      host_id: hostId,
      user_id: customerId,
    });

    return res.status(201).json({
      success: true,
      message: 'Review created successfully',
    });
  } catch (error) {
    next(error);
  }
};

exports.updateReview = async (req, res, next) => {
  try {
    const { userId } = req;
    const { reviewId } = req.params;

    const review = await CustomerReviews.findOne({
      where: { id: reviewId },
    });

    if (!review) {
      return res.status(404).json({
        success: false,
        message: 'Review not found',
      });
    }

    if (review.host_id !== userId) {
      return res.status(403).json({
        success: false,
        message: 'You are not authorized to update this review',
      });
    }

    for (const key of ['rating', 'content']) {
      if (key in req.body) {
        review[key] = req.body[key];
      }
    }

    await review.save();

    return res.status(200).json({
      success: true,
      message: 'Review updated successfully',
    });
  } catch (error) {
    next(error);
  }
};

exports.deleteReview = async (req, res, next) => {
  try {
    const { userId } = req;
    const { reviewId } = req.params;

    const review = await CustomerReviews.findOne({
      where: { id: reviewId },
    });

    if (!review) {
      return res.status(404).json({
        success: false,
        message: 'Review not found',
      });
    }

    if (review.host_id !== userId) {
      return res.status(403).json({
        success: false,
        message: 'You are not authorized to delete this review',
      });
    }

    await review.destroy();

    return res.status(200).json({
      success: true,
      message: 'Review deleted successfully',
    });
  } catch (error) {
    next(error);
  }
};

exports.getReviews = async (req, res, next) => {
  try {
    const { page, limit } = req.query;
    const { customerId } = req.params;

    if (!customerId) {
      return res.status(400).json({
        success: false,
        message: 'Please provide a listing id',
      });
    }

    const reviews = await sequelize.query(
      `
			SELECT
				cr.id,
				cr.rating,
				cr.content,
				cr.createdAt,
				u.id AS userId,
				u.firstName,
				u.lastName,
				u.image,
				u.id as user_id
			FROM customer_reviews cr
			LEFT JOIN users u ON cr.host_id = u.id
			WHERE cr.user_id = ?
			`,
      {
        type: QueryTypes.SELECT,
        replacements: [customerId],
      },
    );

    const cleanReviews = reviews.map((review) => {
      return {
        id: review.id,
        rating: review.rating,
        content: review.content,
        createdAt: formatTimestamp(review.createdAt),
        host: {
          fullname: `${review.firstName || ''} ${review.lastName || ''}`.trim() || 'Deleted User',
          image: review.image
            ? `${process.env.BASE_URL}/public/user-uploads/${review.image}`
            : null,
          id: review.userId,
        },
      };
    });

    if (!page || !limit) {
      return res.status(200).json({
        success: true,
        data: cleanReviews,
      });
    }

    const paginated = paginate(cleanReviews, parseInt(page), parseInt(limit));

    return res.status(200).json({
      success: true,
      ...paginated,
    });
  } catch (error) {
    next(error);
  }
};
