const { parseJsonSafe } = require('../../helpers/jsonResponseParser');
const { Users, Bookings, Listings, CustomerReviews, ListingImages, ListingReviews } = require('../../models');
const { formatTimestamp } = require('../../util');

exports.getProfile = async (req, res, next) => {
	const { userId: reqUserId } = req;
	const { userId } = req.params;

	try {
		const user = await Users.findOne({
			where: {
				id: userId ?? reqUserId,
			},
			attributes: [
				'id',
				'firstname',
				'lastname',
				'createdAt',
				'verified',
				'about_me',
				'work',
				'address_city',
				'address_country',
				'music',
				'pets',
				'hangouts',
				'likes',
				'languages',
				'show_travels',
				'interests',
			],
			include: [
				{
					model: CustomerReviews,
					attributes: ['content', 'createdAt', 'rating'],
					include: [
						{
							model: Users,
							as: 'host',

							attributes: ['id', 'firstname', 'lastname', 'image'],
						},
					],
				},
			],
		});

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

		const bookings = user.show_travels ? await getDoneBookings(userId ?? reqUserId) : null;

		const { reviewsCount, averageRating, customerReviews } = processReviewsData(user.CustomerReviews);

		const data = {
			id: user.id,
			image: user?.image ? `${process.env.BASE_URL}/public/user-uploads/${user.image}` : null,
			fullname: user.firstname + ' ' + user.lastname,
			createdAt: formatTimestamp(user.createdAt),
			reviewsCount,
			averageRating,
			verified: user.verified,
			aboutMe: user.about_me,
			work: user.work,
			address: user.address_city && user.address_country ? `${user.address_city}, ${user.address_country}` : null,
			hobbies: {
				music: user.music,
				pets: user.pets,
				hangouts: user.hangouts,
				likes: user.likes,
				interests: user.interests ? parseJsonSafe(user.interests) : null,
			},
			languages: user.languages ? parseJsonSafe(user.languages) : null,
			lastAdventures: bookings,
			customerReviews,
		};

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

exports.getProfileEdit = async (req, res, next) => {
	const { userId } = req;

	try {
		const user = await Users.findOne({
			where: {
				id: userId,
			},
			attributes: [
				'id',
				'firstname',
				'lastname',
				'image',
				'createdAt',
				'about_me',
				'school',
				'work',
				'music',
				'lived_in',
				'languages',
				'pets',
				'hangouts',
				'birth_year',
				'likes',
				'dislikes',
				'interests',
				'show_travels',
			],
			include: [
				{
					model: CustomerReviews,
					attributes: ['rating'],
				},
			],
		});

		const { averageRating } = processReviewsData(user.CustomerReviews);

		const data = {
			id: user.id,
			fullname: user.firstname + ' ' + user.lastname,
			image: user.image ? `${process.env.BASE_URL}/public/user-uploads/${user.image}` : null,
			createdAt: formatTimestamp(user.createdAt),
			averageRating,
			aboutMe: user.about_me,
			work: user.work,
			school: user.school,
			music: user.music,
			livedIn: user.lived_in,
			languages: user.languages ? parseJsonSafe(user.languages) : null,
			pets: user.pets,
			hangouts: user.hangouts,
			birthYear: user.birth_year,
			likes: user.likes,
			dislikes: user.dislikes,
			interests: user.interests ? parseJsonSafe(user.interests) : null,
			showTravels: user.show_travels,
		};

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

async function getDoneBookings(userId) {
	const bookings = await Bookings.findAll({
		where: {
			customer_id: userId,
			status: 'Done',
		},
		attributes: ['id'],
		include: [
			{
				model: Listings,
				as: 'listing',
				attributes: ['id', 'name', 'address_city', 'address_country'],
				include: [
					{
						model: ListingImages,
						as: 'listingImages',
						attributes: ['image'],
					},
					{
						model: ListingReviews,
						attributes: ['rating'],
						as: 'listingReviews',
					},
				],
			},
		],
	});

	const processedBookings = bookings.map((booking) => {
		let listingRating = null;
		if (booking?.listing?.listingReviews?.length > 0) {
			listingRating =
				booking.listing.listingReviews.reduce((acc, review) => acc + review.rating, 0) /
				booking.listing.listingReviews.length;
			listingRating = listingRating.toFixed(2);
		}

		const hasAddress = booking?.listing?.address_city && booking?.listing?.address_country;
		const address = hasAddress ? booking.listing.address_city + ', ' + booking.listing.address_country : null;

		return {
			name: booking?.listing?.name ?? 'Deleted Listing',
			address,
			image: booking?.listing?.listingImages[0]?.image
				? `${process.env.BASE_URL}/public/host-uploads/${booking.listing.listingImages[0].image}`
				: null,
			averageRating: listingRating,
		};
	});

	return processedBookings;
}

function processReviewsData(data) {
	let averageRating = null;
	if (data.length > 0) {
		averageRating = data.reduce((acc, review) => acc + review.rating, 0) / data.length;
		averageRating = averageRating.toFixed(2);
	}

	const reviewsCount = data.length;
	const customerReviews = data.map((review) => {
		const hasUser = review?.host?.id;
		const hasImage = review?.host?.image;

		return {
			content: review.content,
			createdAt: formatTimestamp(review.createdAt),
			userId: review?.host?.id ?? null,
			fullname: hasUser ? review?.host?.firstname + ' ' + review?.host?.lastname : 'Deleted User',
			image: hasUser && hasImage ? `${process.env.BASE_URL}/public/user-uploads/${review.host.image}` : null,
		};
	});

	return { averageRating, reviewsCount, customerReviews };
}
