const { Op } = require('sequelize');
const { PaymentHistory, Bookings, Users, Listings, ListingImages } = require('../../models');
const { formatTimestamp } = require('../../util/formatTimestamp');

exports.getPaymentHistory = async (req, res) => {
	const { userId } = req;
	const { status, startDate, endDate, payoutMethods, listingIds } = req.query;

	try {
		const filter = {
			customer_id: userId,
		};

		if (status) {
			filter.status = status;
		}

		if (startDate) {
			filter[Op.and] = [
				{
					[Op.or]: [
						{ createdAt: { [Op.gte]: startDate } },
						{ updatedAt: { [Op.gte]: startDate } },
						{ expected_payout: { [Op.gte]: startDate } },
					],
				},
			];
		}

		if (endDate) {
			const endOfDay = new Date(endDate);
			endOfDay.setHours(23, 59, 59, 999);

			if (!filter[Op.and]) {
				filter[Op.and] = [];
			}
			filter[Op.and].push({
				[Op.or]: [
					{ createdAt: { [Op.lte]: endOfDay } },
					{ updatedAt: { [Op.lte]: endOfDay } },
					{ expected_payout: { [Op.lte]: endOfDay } },
				],
			});
		}

		if (payoutMethods) {
			const payoutMethodsArray = Array.isArray(payoutMethods) ? payoutMethods : [payoutMethods];
			filter.payout_method = { [Op.in]: payoutMethodsArray };
		}

		let listingFilter = null;

		if (listingIds && listingIds.length > 0) {
			const listingIdsArray = Array.isArray(listingIds) ? listingIds : [listingIds];

			listingFilter = {
				listing_id: { [Op.in]: listingIdsArray },
			};
		}

		const paymentHistory = await PaymentHistory.findAll({
			where: filter,
			include: [
				{
					model: Bookings,
					attributes: ['id', 'booking_no', 'pax', 'check_in', 'check_out'],
					where: listingFilter,
					include: [
						{
							model: Users,
							as: 'customers',
							attributes: ['id', 'firstname', 'lastname'],
						},
						{
							model: Users,
							as: 'host',
							attributes: ['id', 'firstname', 'lastname'],
						},
						{
							model: Listings,
							attributes: ['id', 'name'],
							as: 'listing',
						},
					],
				},
			],
		});

		const formatted = paymentHistory?.map((payment) => {
			const { Booking: booking } = payment;

			const customerName = booking?.customers?.firstname + ' ' + booking?.customers?.lastname;
			const hostName = booking?.host?.firstname + ' ' + booking?.host?.lastname;

			const reservationDetails = booking && {
				id: booking.id,
				bookingNo: booking.booking_no,
				customerName,
				listingName: booking.listing?.name,
				pax: booking.pax,
				checkIn: booking.check_in,
				checkOut: booking.check_out,
			};

			const payoutMethod = {
				hostName,
				payoutMethod: payment.payout_method,
				total: payment.total,
			};

			const expectedPayout = payment.expected_payout;

			return {
				reservationDetails,
				payoutMethod,
				expectedPayout,
				createdAt: formatTimestamp(payment.createdAt),
				updatedAt: formatTimestamp(payment.updatedAt),
				status: payment.status,
			};
		});

		return res.status(200).json({
			success: true,
			data: formatted,
		});
	} catch (error) {
		return res.status(500).json({ message: error.message });
	}
};

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

	try {
		const paymentHistory = await PaymentHistory.findAll({
			where: {
				customer_id: userId,
			},
			attributes: ['payout_method'],
			include: [
				{
					model: Bookings,
					attributes: ['id', 'listing_id'],
					include: [
						{
							model: Listings,
							attributes: ['id', 'name'],
							as: 'listing',

							include: [
								{
									model: ListingImages,
									attributes: ['image'],
									as: 'listingImages',
								},
							],
						},
					],
				},
			],
		});

		const { payoutMethods, listings } = paymentHistory.reduce(
			(acc, curr) => {
				const { payoutMethods, listings } = acc;

				const validPayout = !payoutMethods.includes(curr.payout_method);
				if (validPayout) {
					payoutMethods.push(curr.payout_method);
				}

				const listing = curr.Booking?.listing;
				const validListing = listing && !listings?.some((l) => l.id === listing.id);

				if (validListing) {
					let image = listing?.listingImages[0]?.image ?? null;
					if (image) {
						image = `${process.env.BASE_URL}/public/host-uploads/${image}`;
					}

					listings.push({ id: listing?.id, name: listing?.name, image });
				} else {
					listings.push({ id: curr.Booking?.listing_id, name: 'Unknown Listing', image: null });
				}

				return acc;
			},
			{ payoutMethods: [], listings: [] },
		);

		return res.status(200).json({
			success: true,
			data: { payoutMethods, listings },
		});
	} catch (error) {
		return res.status(500).json({ message: error.message });
	}
};
