const { QueryTypes } = require('sequelize');
const { ListingReviews, Listings, sequelize } = require('../../models');
const { paginate } = require('../../util/pagination');
const { formatTimestamp } = require('../../util');

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

		const listing = await Listings.findByPk(listingId);

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

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

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

		await ListingReviews.create({
			content: req.body.content,
			rating: req.body.rating,
			listing_id: listingId,
			user_id: userId,
		});

		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 ListingReviews.findOne({
			where: { id: reviewId },
		});

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

		if (review.user_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 ListingReviews.findOne({
			where: { id: reviewId },
		});

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

		if (review.user_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 { listingId } = req.params;

		if (!listingId) {
			return res.status(400).json({
				success: false,
				message: 'Please provide a listing id',
			});
		}
		const hostReviews = await sequelize.query(
			`
			SELECT
				lr.id,
				lr.rating,
				lr.content,
				lr.createdAt,
				u.id AS userId,
				u.firstName,
				u.lastName,
				u.image,
				u.id as user_id
			FROM listing_reviews lr
			LEFT JOIN users u ON lr.user_id = u.id
			WHERE lr.listing_id = ?
			`,
			{
				type: QueryTypes.SELECT,
				replacements: [listingId],
			},
		);

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

		const paginated = paginate(cleanHostReviews, req.query.page, req.query.limit);

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