import type { ReturnReason } from '@/server/domain/returns/machine';
import { STATUTORY_CANCELLATION_WINDOW_DAYS, statutoryRefund } from '@/server/domain/refund/policy';
import { isDealCategoryStatutoryExempt } from '@/server/domain/refund/category-exemptions';

export const IL_RETURN_FLOOR_DAYS = STATUTORY_CANCELLATION_WINDOW_DAYS;
export const MAX_PHOTOS = 6;
export const SHIPPING_REIMBURSEMENT_MAX_PCT = 0.5;

const VENDOR_LIABILITY_REASONS = new Set<ReturnReason>([
  'defective',
  'damaged_in_transit',
  'not_as_described',
  'wrong_item_received',
  'arrived_late',
]);
const PHOTOS_REQUIRED_REASONS = new Set<ReturnReason>([
  'defective',
  'damaged_in_transit',
  'wrong_item_received',
]);

export function deriveLiability(reason: ReturnReason): 'vendor' | 'buyer' {
  return VENDOR_LIABILITY_REASONS.has(reason) ? 'vendor' : 'buyer';
}

export function computeRefundBreakdown(input: {
  amountPaidAgorot: number;
  reason: ReturnReason;
  vendorRestockingPct: number;
  returnShippingCostAgorot: number;
  categorySlug?: string | null;
}): {
  refundAmountAgorot: number;
  restockingFeeAgorot: number;
  shippingReimbursementAgorot: number;
} {
  const liability = deriveLiability(input.reason);
  const refundAmountAgorot = input.amountPaidAgorot;
  const restockingFeeAgorot = statutoryRefund({
    dealType: 'ITEM',
    amountPaidAgorot: input.amountPaidAgorot,
    purchasedAt: new Date(0),
    deliveredAt: new Date(0),
    serviceDate: null,
    cancelledAt: new Date(0),
    reason: liability === 'vendor' ? 'defect' : 'consumer_remorse',
    exempt: isDealCategoryStatutoryExempt(input.categorySlug),
    redeemedAt: null,
  }).feeAgorot;
  let shippingReimbursementAgorot = 0;
  if (liability === 'vendor') {
    const rawCost = Number.isFinite(input.returnShippingCostAgorot)
      ? input.returnShippingCostAgorot
      : 0;
    const cap = Math.round(input.amountPaidAgorot * SHIPPING_REIMBURSEMENT_MAX_PCT);
    shippingReimbursementAgorot = Math.min(Math.max(0, rawCost), cap);
  }
  return { refundAmountAgorot, restockingFeeAgorot, shippingReimbursementAgorot };
}

export function computeHybridSplit(input: {
  amountPaidAgorot: number;
  buyerRefundAgorot: number;
}): { cashRefundAgorot: number; creditOverflowAgorot: number } {
  const cashRefundAgorot = Math.min(input.buyerRefundAgorot, input.amountPaidAgorot);
  const creditOverflowAgorot = Math.max(0, input.buyerRefundAgorot - cashRefundAgorot);
  return { cashRefundAgorot, creditOverflowAgorot };
}

export function eligibleToOpenReturn(input: {
  purchase: { paymentStatus: string; redemptionStatus: string; deliveredAt: Date | null };
  deal: { isPhysical: boolean; isReturnable: boolean; returnWindowDays: number };
  openReturnExists: boolean;
  now: Date;
}): { ok: true } | { ok: false; reason: string } {
  if (!input.deal.isPhysical) return { ok: false, reason: 'not_physical' };
  if (!input.deal.isReturnable) return { ok: false, reason: 'not_returnable' };
  if (input.openReturnExists) return { ok: false, reason: 'open_return_exists' };
  const paymentStatus = input.purchase.paymentStatus.toUpperCase();
  if (!['COMPLETED', 'PAID', 'FULFILLED'].includes(paymentStatus)) {
    return { ok: false, reason: 'not_completed' };
  }
  if (input.purchase.redemptionStatus === 'REDEEMED') return { ok: false, reason: 'redeemed' };
  if (!input.purchase.deliveredAt) return { ok: false, reason: 'not_delivered' };
  const deliveredMs = input.purchase.deliveredAt.getTime();
  if (!Number.isFinite(deliveredMs)) return { ok: false, reason: 'invalid_delivered_at' };
  const rawWindow = Number.isFinite(input.deal.returnWindowDays) ? input.deal.returnWindowDays : 0;
  const windowDays = Math.max(rawWindow, IL_RETURN_FLOOR_DAYS);
  const deadline = new Date(deliveredMs + windowDays * 86400_000);
  if (input.now > deadline) return { ok: false, reason: 'window_passed' };
  return { ok: true };
}

export function validateReturnRequest(input: {
  reason: ReturnReason;
  photoCount: number;
}): { ok: true } | { ok: false; reason: string } {
  if (input.photoCount > MAX_PHOTOS) return { ok: false, reason: 'too_many_photos' };
  if (PHOTOS_REQUIRED_REASONS.has(input.reason) && input.photoCount < 1) {
    return { ok: false, reason: 'photo_required' };
  }
  return { ok: true };
}
