const { deleteFile } = require('../../helpers');
const {
	Activities,
	ActivityImages,
	ActivityLikes,
	ActivityReviews,
	ActivityReviewImages,
	ActivityItineraries,
} = require('../../models');
const { formatImage, parseJsonSafe } = require('../../util/formatter');

exports.createActivity = async (req, res, next) => {
	const sequelize = Activities.sequelize;
	const transaction = await sequelize.transaction();
	try {
		let activity = await Activities.create(
			{ ...req.body, about: JSON.stringify(parseJsonSafe(req.body.about)) },
			{ transaction },
		);

		let images = [];

		const activityImgs = req?.files?.activityImgs;

		if (activityImgs?.length > 0) {
			const oldImages = await ActivityImages.findAll({
				where: { activity_id: activity.id },
			});

			for (const oldImage of oldImages) {
				if (oldImage.image) {
					deleteFile(oldImage.image, 'activity-uploads');
				}
				await oldImage.destroy({ transaction });
			}

			for (const img of activityImgs) {
				const image = await ActivityImages.create(
					{
						activity_id: activity.id,
						image: img.filename,
					},
					{ transaction },
				);
				images.push(image);
			}
		}

		const itineraries = parseJsonSafe(req.body.itineraries);

		let itineraryRecords = [];
		for (const itinerary of itineraries || []) {
			let record = await ActivityItineraries.create(
				{
					activity_id: activity.id,
					...itinerary,
				},
				{ transaction },
			);
			itineraryRecords.push(record);
		}

		await transaction.commit();
		activity = activity.get({ plain: true });
		activity.images = images ? images.map((img) => ({ image: formatImage(img.image) })) : [];
		activity.itineraries = itineraryRecords;

		return res.status(201).json({ success: true, data: activity });
	} catch (error) {
		if (transaction) await transaction.rollback();
		next(error);
	}
};

exports.getAllActivities = async (req, res, next) => {
	try {
		const activities = await Activities.findAll({
			include: [
				{ model: ActivityImages, as: 'images' },
				{ model: ActivityLikes, as: 'likes' },
				{
					model: ActivityReviews,
					as: 'reviews',
					include: [{ model: ActivityReviewImages, as: 'images' }],
				},
				{ model: ActivityItineraries, as: 'itineraries' },
			],
		});

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

exports.getActivity = async (req, res, next) => {
	try {
		const activity = await Activities.findByPk(req.params.id, {
			include: [
				{ model: ActivityImages, as: 'images' },
				{ model: ActivityLikes, as: 'likes' },
				{
					model: ActivityReviews,
					as: 'reviews',
					include: [{ model: ActivityReviewImages, as: 'images' }],
				},
				{ model: ActivityItineraries, as: 'itineraries' },
			],
		});
		if (!activity) return res.status(404).json({ success: false, message: 'Activity not found' });
		return res.status(200).json({ success: true, data: activity });
	} catch (error) {
		next(error);
	}
};

exports.updateActivity = async (req, res, next) => {
	try {
		const activity = await Activities.findByPk(req.params.id);
		if (!activity) return res.status(404).json({ success: false, message: 'Activity not found' });
		await activity.update(req.body);
		return res.status(200).json({ success: true, data: activity });
	} catch (error) {
		next(error);
	}
};

exports.deleteActivity = async (req, res, next) => {
	const sequelize = Activities.sequelize;
	const transaction = await sequelize.transaction();
	try {
		const activity = await Activities.findByPk(req.params.id);
		let files = [];
		if (!activity) {
			await transaction.rollback();
			return res.status(404).json({ success: false, message: 'Activity not found' });
		}

		const activityImages = await ActivityImages.findAll({ where: { activity_id: activity.id } });
		for (const image of activityImages) {
			if (image.image) {
				files.push(image.image);
			}
			await image.destroy({ transaction });
		}

		await ActivityLikes.destroy({ where: { activity_id: activity.id }, transaction });

		const reviews = await ActivityReviews.findAll({ where: { activity_id: activity.id } });
		for (const review of reviews) {
			await ActivityReviewImages.destroy({ where: { reviewId: review.id }, transaction });
		}

		await ActivityReviews.destroy({ where: { activity_id: activity.id }, transaction });

		await ActivityItineraries.destroy({ where: { activity_id: activity.id }, transaction });

		await activity.destroy({ transaction });

		await transaction.commit();

		for (const file of files) {
			deleteFile(file, 'activity-uploads');
		}

		return res.status(200).json({ success: true, message: 'Activity and related data deleted' });
	} catch (error) {
		if (transaction) await transaction.rollback();
		next(error);
	}
};

exports.highlightReview = async (req, res, next) => {
	const { reviewId, highlight } = req.body;

	const review = await ActivityReviews.findByPk(reviewId);
	if (!review) {
		return res.status(404).json({ success: false, message: 'Review not found' });
	}
	review.is_highlighted = highlight;
	await review.save();
	return res.status(200).json({ success: true, message: 'Review highlight status updated', data: review });
};
