const {
  UUID,
  UUIDV4,
  DECIMAL,
  STRING,
  TEXT,
  INTEGER,
  DATEONLY,
  ENUM,
  BOOLEAN,
  JSON,
  FLOAT,
} = require('sequelize');

module.exports = (sequelize, DataTypes) => {
  const Bookings = sequelize.define(
    'Bookings',
    {
      id: {
        type: UUID,
        defaultValue: UUIDV4,
        allowNull: false,
        primaryKey: true,
      },
      customer_id: {
        type: UUID,
        allowNull: false,
      },
      host_id: {
        type: UUID,
        allowNull: false,
      },
      listing_id: {
        type: UUID,
        allowNull: false,
      },
      booking_no: {
        type: STRING(20),
        allowNull: false,
      },
      check_in: {
        type: DATEONLY,
        allowNull: false,
      },
      check_out: {
        type: DATEONLY,
        allowNull: false,
      },
      pax: {
        type: INTEGER,
        allowNull: false,
        defaultValue: 1,
      },
      price_per_night: {
        type: DECIMAL(10, 2),
        allowNull: false,
        defaultValue: 0.0,
      },
      subtotal: {
        type: DECIMAL(10, 2),
        allowNull: false,
      },
      total_amount: {
        type: DECIMAL(10, 2),
        allowNull: false,
        defaultValue: 0.0,
      },
      amount_paid: {
        type: DECIMAL(10, 2),
        allowNull: false,
        defaultValue: 0.0,
      },
      payment_status: {
        type: ENUM('Fully Paid', 'Unpaid', 'Partially Paid', 'Failed'),
        allowNull: false,
        defaultValue: 'Unpaid',
      },
      balance: {
        type: DECIMAL(10, 2),
        allowNull: false,
        defaultValue: 0.0,
      },
      payment_method: {
        type: STRING,
        allowNull: true,
      },
      message_to_host: {
        type: TEXT,
        allowNull: true,
      },
      user_image: {
        type: STRING,
        allowNull: true,
      },
      status: {
        type: ENUM(
          'Unpaid',
          'For Approval',
          'Done',
          'Upcoming',
          'Cancelled',
          'Ongoing',
          'Declined',
        ),
        allowNull: false,
        defaultValue: 'Unpaid',
      },
      is_rescheduled: {
        type: BOOLEAN,
        allowNull: false,
        defaultValue: false,
      },
      updates_data: {
        type: JSON,
        allowNull: true,
      },
      cancellation_reason: {
        type: TEXT,
        allowNull: true,
      },
      listing_spot_id: {
        type: UUID,
        allowNull: true,
      },
      phone_no: {
        type: STRING,
        allowNull: true,
      },
      email: {
        type: STRING,
        allowNull: true,
      },
      fullname: {
        type: STRING,
        allowNull: true,
      },
      discount_code: {
        type: STRING,
        allowNull: true,
      },
      discount_percentage: {
        type: FLOAT,
        allowNull: true,
      },
      discount_amount: {
        type: FLOAT,
        allowNull: true,
      },
      discount_num_of_pax: {
        type: INTEGER,
        allowNull: true,
      },
      discount_amount_to_reach: {
        type: DECIMAL(10, 2),
        allowNull: true,
      },
      discount_type: {
        type: STRING,
        allowNull: true,
      },
      guest_fee: {
        type: DECIMAL(10, 2),
        allowNull: false,
      },
      host_fee: {
        type: DECIMAL(10, 2),
        allowNull: false,
      },
      total_host_income: {
        type: DECIMAL(10, 2),
        allowNull: false,
      },
      aircamp_income: {
        type: DECIMAL(10, 2),
        allowNull: false,
      },
      modify_request: {
        type: ENUM('Pending', 'Accepted', 'Rejected'),
        allowNull: true,
      },
      email_on_response: {
        type: BOOLEAN,
        allowNull: true,
      },
      host_modification_fee: {
        type: FLOAT,
        allowNull: true,
      },
      service_fee: {
        type: DECIMAL(10, 2),
        allowNull: false,
        defaultValue: 0.0,
      },
      payment_intent_id: {
        type: STRING,
        allowNull: true,
      },
      paymongo_payment_id: {
        type: STRING,
        allowNull: true,
      },
      paymongo_fee: {
        type: DECIMAL(10, 2),
        allowNull: true,
      },
      is_refunded: {
        type: BOOLEAN,
        allowNull: false,
        defaultValue: false,
      },
      refund_amount: {
        type: DECIMAL(10, 2),
        allowNull: true,
      },
      refund_percentage: {
        type: FLOAT,
        allowNull: true,
      },
      refunded_at: {
        type: DataTypes.DATE,
        allowNull: true,
      },
      paymongo_refund_id: {
        type: STRING,
        allowNull: true,
      },
      is_customer_modified: {
        type: BOOLEAN,
        allowNull: false,
        defaultValue: false,
      },
      customer_modify_payment_status: {
        type: ENUM('Unpaid', 'Paid', 'Failed'),
        allowNull: true,
      },
      customer_modify_payment: {
        type: DECIMAL(10, 2),
        allowNull: true,
      },
      host_modify_payment_status: {
        type: ENUM('Unpaid', 'Paid', 'Failed'),
        allowNull: true,
      },
      // cleaning_fee: {
      // 	type: FLOAT,
      // 	allowNull: true,
      // },
      // security_deposit: {
      // 	type: FLOAT,
      // 	allowNull: true,
      // },
      // government_id: {
      // 	type: STRING,
      // 	allowNull: true,
      // },
    },
    {
      tableName: 'bookings',
      timestamps: true,
      hooks: {
        afterCreate: async (booking, options) => {
          try {
            const { HostNotifications } = sequelize.models;

            const message = `A new booking has been created. Check-in is scheduled for ${booking.check_in}.`;

            await HostNotifications.create({
              host_id: booking.host_id,
              booking_id: booking.id,
              notif_type: 'New Booking',
              message,
              status: 'Unread',
            });

            // console.log(`Notification for new booking (ID: ${booking.id}) created.`);
          } catch (error) {
            console.error('Error creating notification for new booking:', error.message);
          }
        },
      },
    },
  );

  Bookings.associate = (models) => {
    Bookings.belongsTo(models.Listings, {
      foreignKey: 'listing_id',
      as: 'listing',
    });

    Bookings.hasMany(models.BookingAddOns, {
      foreignKey: 'booking_id',
      as: 'addOns',
    });

    Bookings.belongsTo(models.Users, {
      foreignKey: 'customer_id',
      as: 'customers',
    });

    Bookings.belongsTo(models.Users, {
      foreignKey: 'host_id',
      as: 'host',
    });

    Bookings.belongsTo(models.ListingSpots, {
      foreignKey: 'listing_spot_id',
      as: 'spot',
    });

    Bookings.hasOne(models.ListingReviews, {
      foreignKey: 'booking_id',
      as: 'listingReview',
    });

    Bookings.hasOne(models.HostReviews, {
      foreignKey: 'booking_id',
      as: 'hostReview',
    });

    Bookings.hasMany(models.BookingAdditionalPayments, {
      foreignKey: 'booking_id',
      as: 'additionalPayments',
    });
  };

  return Bookings;
};
