import { Schema } from "mongoose";
import { applyIdTransform, registerModel, stringId } from "../schema";
import { createId } from "../ids";
import { BOOKING_STATUSES, PAYMENT_PROVIDERS, PAYMENT_STATUSES } from "../types";

const PaymentSchema = new Schema(
  {
    _id: { type: String, default: createId },
    provider: { type: String, enum: PAYMENT_PROVIDERS, default: "DEMO" },
    status: { type: String, enum: PAYMENT_STATUSES, default: "PENDING" },
    providerRef: { type: String, default: undefined },
    amount: { type: Number, required: true },
    currency: { type: String, default: "LYD" },
    metadata: { type: Schema.Types.Mixed, default: undefined },
    paidAt: { type: Date, default: undefined },
    createdAt: { type: Date, default: Date.now },
    updatedAt: { type: Date, default: Date.now },
  },
  { _id: true },
);

const InvoiceSchema = new Schema(
  {
    _id: { type: String, default: createId },
    invoiceNumber: { type: String, required: true },
    total: { type: Number, required: true },
    currency: { type: String, default: "LYD" },
    issuedAt: { type: Date, default: Date.now },
    createdAt: { type: Date, default: Date.now },
    /** Snapshot fields — frozen at issue time */
    bookingId: { type: String, default: undefined },
    guestName: { type: String, default: undefined },
    guestEmail: { type: String, default: undefined },
    guestPhone: { type: String, default: undefined },
    propertyTitleAr: { type: String, default: undefined },
    propertyTitleEn: { type: String, default: undefined },
    propertyAddress: { type: String, default: undefined },
    cityNameAr: { type: String, default: undefined },
    cityNameEn: { type: String, default: undefined },
    hostName: { type: String, default: undefined },
    checkIn: { type: Date, default: undefined },
    checkOut: { type: Date, default: undefined },
    nights: { type: Number, default: undefined },
    guests: { type: Number, default: undefined },
    nightlyRateTnd: { type: Number, default: undefined },
    subtotalTnd: { type: Number, default: undefined },
    cleaningFeeTnd: { type: Number, default: undefined },
    platformFeeTnd: { type: Number, default: undefined },
    taxesTnd: { type: Number, default: undefined },
    discountTnd: { type: Number, default: undefined },
    totalTnd: { type: Number, default: undefined },
    totalLyd: { type: Number, default: undefined },
    exchangeRateRate: { type: Number, default: undefined },
    paymentStatus: { type: String, default: undefined },
    paymentProvider: { type: String, default: undefined },
    bookingStatus: { type: String, default: undefined },
  },
  { _id: true },
);

const BookingSchema = new Schema(
  {
    _id: stringId,
    propertyId: { type: String, ref: "Property", required: true },
    customerId: { type: String, ref: "User", required: true },
    ownerId: { type: String, ref: "User", required: true },
    checkIn: { type: Date, required: true },
    checkOut: { type: Date, required: true },
    guests: { type: Number, required: true },
    nights: { type: Number, required: true },
    status: { type: String, enum: BOOKING_STATUSES, default: "PENDING_PAYMENT" },
    exchangeFromCurrency: { type: String, default: "TND" },
    exchangeToCurrency: { type: String, default: "LYD" },
    exchangeRateRate: { type: Number, required: true },
    exchangeRateLockedAt: { type: Date, required: true },
    exchangeRateExpiresAt: { type: Date, required: true },
    subtotalTnd: { type: Number, required: true },
    cleaningFeeTnd: { type: Number, required: true },
    platformFeeTnd: { type: Number, required: true },
    taxesTnd: { type: Number, required: true },
    discountTnd: { type: Number, default: 0 },
    totalTnd: { type: Number, required: true },
    totalLyd: { type: Number, required: true },
    ownerPayoutTnd: { type: Number, required: true },
    couponCode: { type: String, default: undefined },
    walletPaidLyd: { type: Number, default: 0 },
    pointsEarned: { type: Number, default: 0 },
    pointsRedeemed: { type: Number, default: 0 },
    pointsDiscountTnd: { type: Number, default: 0 },
    refundLyd: { type: Number, default: 0 },
    refundPercent: { type: Number, default: 0 },
    /** Who cancelled/rejected — for traveler-facing copy */
    cancelledBy: {
      type: String,
      enum: ["CUSTOMER", "OWNER", "ADMIN"],
      default: undefined,
    },
    cancelledAt: { type: Date, default: undefined },
    deletedAt: { type: Date, default: undefined },
    payment: { type: PaymentSchema, default: undefined },
    invoice: { type: InvoiceSchema, default: undefined },
  },
  { timestamps: true },
);

BookingSchema.index({ customerId: 1, status: 1 });
BookingSchema.index({ ownerId: 1, status: 1 });
BookingSchema.index({ propertyId: 1, checkIn: 1, checkOut: 1 });
BookingSchema.index({ deletedAt: 1 });
BookingSchema.index({ "payment.status": 1 });
BookingSchema.index({ "invoice.invoiceNumber": 1 }, { unique: true, sparse: true });
applyIdTransform(BookingSchema);

export const Booking = registerModel("Booking", BookingSchema);
