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 });
  }
};
