import { prisma } from '../config/database.js';
import type { Booking, CancellationPolicy, BookingStatus } from '@prisma/client';

/**
 * Checks whether a rental listing is available for the given date range.
 * Returns true if no blocked AvailabilityBlock and no CONFIRMED/ACTIVE booking overlaps.
 */
export async function checkAvailability(
  rentalListingId: string,
  startDate: Date,
  endDate: Date
): Promise<boolean> {
  const [blockedCount, bookingCount] = await Promise.all([
    prisma.availabilityBlock.count({
      where: {
        rentalListingId,
        isBlocked: true,
        startDate: { lt: endDate },
        endDate: { gt: startDate },
      },
    }),
    prisma.booking.count({
      where: {
        rentalListingId,
        status: { in: ['CONFIRMED', 'ACTIVE'] },
        startDate: { lt: endDate },
        endDate: { gt: startDate },
      },
    }),
  ]);

  return blockedCount === 0 && bookingCount === 0;
}

/**
 * Calculates cancellation refund amounts based on the listing's cancellation policy.
 *
 * - FLEXIBLE:  >7 days = 100%, 1-7 days = 100%, <24h = 50%. Deposit always returned.
 * - MODERATE:  >7 days = 100%, 1-7 days = 50%,  <24h = 0%.  Deposit always returned.
 * - STRICT:    >7 days = 50%,  1-7 days = 0%,   <24h = 0%.  Deposit always returned.
 */
export function calculateCancellationRefund(
  policy: CancellationPolicy,
  startDate: Date,
  subtotal: number,
  depositAmount: number
): { refundAmount: number; depositRefund: number } {
  const now = new Date();
  const msUntilStart = startDate.getTime() - now.getTime();
  const hoursUntilStart = msUntilStart / (1000 * 60 * 60);
  const daysUntilStart = hoursUntilStart / 24;

  let refundPercent: number;

  switch (policy) {
    case 'FLEXIBLE':
      if (hoursUntilStart < 24) {
        refundPercent = 50;
      } else {
        refundPercent = 100;
      }
      break;

    case 'MODERATE':
      if (hoursUntilStart < 24) {
        refundPercent = 0;
      } else if (daysUntilStart <= 7) {
        refundPercent = 50;
      } else {
        refundPercent = 100;
      }
      break;

    case 'STRICT':
      if (daysUntilStart > 7) {
        refundPercent = 50;
      } else {
        refundPercent = 0;
      }
      break;
  }

  const refundAmount = Math.round((subtotal * refundPercent) / 100 * 100) / 100;
  const depositRefund = depositAmount;

  return { refundAmount, depositRefund };
}

/**
 * Calculates the price breakdown for a booking.
 */
export function calculateBookingPrice(
  pricePerPeriod: number,
  totalPeriods: number,
  commissionRate: number,
  depositAmount: number
): { subtotal: number; commissionAmount: number; totalAmount: number } {
  const subtotal = Math.round(pricePerPeriod * totalPeriods * 100) / 100;
  const commissionAmount = Math.round(subtotal * (commissionRate / 100) * 100) / 100;
  const totalAmount = Math.round((subtotal + commissionAmount + depositAmount) * 100) / 100;

  return { subtotal, commissionAmount, totalAmount };
}

/**
 * Performs lazy status transitions on a booking:
 *
 * - PENDING + expiresAt < now  -> EXPIRED
 * - CONFIRMED + startDate <= now -> ACTIVE
 * - ACTIVE + endDate <= now    -> COMPLETED
 *
 * Returns the updated booking if a transition occurred, or the original booking otherwise.
 */
export async function autoTransitionBooking(booking: Booking): Promise<Booking> {
  const now = new Date();
  let newStatus: BookingStatus | null = null;

  if (booking.status === 'PENDING' && booking.expiresAt && booking.expiresAt < now) {
    newStatus = 'EXPIRED';
  } else if (booking.status === 'CONFIRMED' && booking.startDate <= now) {
    newStatus = 'ACTIVE';
  } else if (booking.status === 'ACTIVE' && booking.endDate <= now) {
    newStatus = 'COMPLETED';
  }

  if (newStatus) {
    return prisma.booking.update({
      where: { id: booking.id },
      data: { status: newStatus },
    });
  }

  return booking;
}
