const { Op } = require('sequelize');
const { Bookings, Listings, ListingImages, Users, BookingAddOns } = require('../../models');
const { paginate } = require('../../util/pagination');
const { checkManagerAccess } = require('../../helpers/managers');

exports.hostCalendar = async (req, res, next) => {
  const { startDate, endDate, listingId, page, limit } = req.query;

  try {
    if (!startDate || !endDate) {
      return res
        .status(400)
        .json({ success: false, message: 'Start date and end date are required' });
    }

    let hostId = req.userId;
    if (req.query.hostId) {
      hostId = (await checkManagerAccess(req)).hostId;
    }

    const filter = {
      host_id: hostId,
      [Op.or]: {
        check_in: {
          [Op.between]: [startDate, endDate],
        },
        check_out: {
          [Op.between]: [startDate, endDate],
        },
      },
    };

    if (listingId) {
      filter.listing_id = listingId;
    }

    const data = await Bookings.findAll({
      where: {
        ...filter,
      },
      attributes: [
        'id',
        'check_in',
        'check_out',
        'status',
        'pax',
        'createdAt',
        'payment_method',
        'payment_status',
        'listing_id',
        'amount_paid',
        'balance',
        'total_amount',
        'phone_no',
      ],
      include: [
        {
          model: Listings,
          as: 'listing',
          attributes: ['id', 'name', 'address_city', 'address_country', 'price'],
          include: [
            {
              model: ListingImages,
              as: 'listingImages',
              attributes: ['image'],
            },
          ],
        },
        {
          model: Users,
          as: 'customers',
          attributes: ['id', 'firstname', 'lastname', 'image', 'address_city', 'address_country'],
        },
        {
          model: BookingAddOns,
          as: 'addOns',
          attributes: ['id', 'add_on_name', 'quantity', 'price', 'total_amount'],
        },
      ],
    });

    const mappedData = data?.map((booking) => {
      const bookingData = booking;
      const listing = bookingData?.listing ?? {};
      const customer = bookingData?.customers ?? {};

      const mapData = {
        id: bookingData.id,
        checkIn: bookingData.check_in,
        checkOut: bookingData.check_out,
        status: bookingData.status,
        pax: bookingData.pax,
        createdAt: bookingData.createdAt,
        paymentMethod: bookingData.payment_method,
        paymentStatus: bookingData.payment_status,
        price: listing.price,
        amountPaid: bookingData.amount_paid,
        balance: bookingData.balance,
        totalAmount: bookingData.total_amount,
        phoneNo: customer.phone_no,
      };

      const listingData = listing?.id
        ? {
            id: listing.id,
            name: listing.name,
            address:
              listing.address_city && listing.address_country
                ? `${listing.address_city}, ${listing.address_country}`
                : null,
            price: listing.price,
            image: listing?.listingImages?.[0]?.image
              ? `${process.env.BASE_URL}/public/host-uploads/${listing.listingImages[0].image}`
              : null,
          }
        : null;

      const customerData = customer?.id
        ? {
            fullname: `${customer.firstname} ${customer.lastname}`,
            image: customer.image
              ? `${process.env.BASE_URL}/public/user-uploads/${customer.image}`
              : null,
            address:
              customer.address_city && customer.address_country
                ? `${customer.address_city}, ${customer.address_country}`
                : null,
          }
        : null;

      const addOns =
        bookingData?.addOns?.length > 0
          ? bookingData?.addOns?.map((addOn) => ({
              id: addOn.id,
              name: addOn.add_on_name,
              price: addOn.price,
              quantity: addOn.quantity,
              totalAmount: addOn.total_amount,
            }))
          : null;

      return {
        ...mapData,
        listing: listingData,
        customer: customerData,
        addOns,
      };
    });

    if (!page || !limit) {
      return res.status(200).json({
        success: true,
        data: mappedData,
      });
    }

    const paginated = paginate(mappedData, parseInt(page), parseInt(limit));

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