/* booking-engine.jsx — shared booking helpers + price logic
   Used by mini-selector, home reservar section, and reservar.html wizard.
   Currency: EUR. All prices VAT-incl. */

const PRICING = {
  // Base price per night for the entire building (10 guests)
  base:        420,   // weekday (Mon–Thu)
  weekend:     520,   // Fri/Sat night
  // Direct booking discount applied on top
  directDiscountPct:      10,   // entire building
  directDiscountRoomPct:   5,   // individual rooms
  // Non-refundable rate extra discount on top
  nonRefundableExtraPct: 10,
  // Min stay
  minStayWeekend: 2,
  minStayWeekday: 1,
  // Max guests
  maxGuests: 10,
  currency: '€',
};

// -------- room inventory --------
// Placeholder prices — these will come from Smoobu API in production.
// Sum of rooms (L-J): 90+115+95+105+85 = 490 → > 420 building base, so the
// "entire building" is genuinely cheaper than rooms à la carte. ✓
const ROOMS = [
  { id:'01', key:'r_01', baseLJ: 90, baseVS:110, capacity:2, bath:'acc',
    img:'images/cama_habitacion_2.jpeg' },
  { id:'02', key:'r_02', baseLJ:115, baseVS:140, capacity:2, bath:'private',
    img:'images/habitacion_3_lavabo.jpeg' },
  { id:'03', key:'r_03', baseLJ: 95, baseVS:115, capacity:2, bath:'shared',
    img:'images/habitacion_3_escritorio.jpeg' },
  { id:'04', key:'r_04', baseLJ:105, baseVS:130, capacity:2, bath:'private',
    img:'images/habitacion_4_2_camas.jpeg' },
  { id:'05', key:'r_05', baseLJ: 85, baseVS:105, capacity:2, bath:'shared',
    img:'images/habitacion_5.jpeg' },
];
function getRoom(id) { return ROOMS.find(r => r.id === id) || null; }

// -------- date helpers --------
function todayISO() {
  const d = new Date(); d.setHours(0,0,0,0);
  return toISO(d);
}
function toISO(d) {
  const y = d.getFullYear(), m = String(d.getMonth()+1).padStart(2,'0'), day = String(d.getDate()).padStart(2,'0');
  return `${y}-${m}-${day}`;
}
function fromISO(s) {
  if (!s) return null;
  const [y, m, d] = s.split('-').map(Number);
  return new Date(y, m-1, d);
}
function addDays(s, n) {
  const d = fromISO(s); d.setDate(d.getDate()+n);
  return toISO(d);
}
function diffNights(a, b) {
  if (!a || !b) return 0;
  const da = fromISO(a), db = fromISO(b);
  return Math.round((db - da) / 86400000);
}
function isWeekendNight(iso) {
  // night STARTING on iso. Fri or Sat night.
  const d = fromISO(iso);
  const dow = d.getDay(); // 0=Sun..6=Sat
  return dow === 5 || dow === 6;
}
function fmtDate(iso, lang) {
  if (!iso) return '—';
  const d = fromISO(iso);
  const opts = { day:'numeric', month:'short' };
  return d.toLocaleDateString(lang === 'en' ? 'en-GB' : lang === 'fr' ? 'fr-FR' : 'es-ES', opts);
}
function fmtDateLong(iso, lang) {
  if (!iso) return '—';
  const d = fromISO(iso);
  return d.toLocaleDateString(lang === 'en' ? 'en-GB' : lang === 'fr' ? 'fr-FR' : 'es-ES',
    { weekday:'short', day:'numeric', month:'long', year:'numeric' });
}
function fmtMoney(n) {
  return `${PRICING.currency}${Math.round(n).toLocaleString('es-ES')}`;
}

// -------- pricing --------
// Returns total for given dates (excl. discounts), for the ENTIRE BUILDING.
function basePriceForRange(checkIn, checkOut) {
  if (!checkIn || !checkOut) return 0;
  let total = 0;
  let cur = checkIn;
  while (cur < checkOut) {
    total += isWeekendNight(cur) ? PRICING.weekend : PRICING.base;
    cur = addDays(cur, 1);
  }
  return total;
}
// Room subtotal across the range (no discount).
function roomBasePriceForRange(roomId, checkIn, checkOut) {
  if (!checkIn || !checkOut) return 0;
  const r = getRoom(roomId); if (!r) return 0;
  let total = 0, cur = checkIn;
  while (cur < checkOut) {
    total += isWeekendNight(cur) ? r.baseVS : r.baseLJ;
    cur = addDays(cur, 1);
  }
  return total;
}
// Sum of all 5 rooms across the range.
function allRoomsBasePriceForRange(checkIn, checkOut) {
  return ROOMS.reduce((s, r) => s + roomBasePriceForRange(r.id, checkIn, checkOut), 0);
}
// What you save by booking the entire building vs all 5 rooms (after discounts).
function buildingSavingsVsAllRooms(checkIn, checkOut) {
  const buildingTotal  = priceQuote({ mode:'full',  checkIn, checkOut, rate:'flex' }).total;
  const allRoomsTotal  = priceQuote({ mode:'rooms', checkIn, checkOut, rate:'flex',
                                      rooms: ROOMS.map(r => r.id) }).total;
  return Math.max(0, allRoomsTotal - buildingTotal);
}
// ----- unified price quote -----
// args: { mode:'full'|'rooms', checkIn, checkOut, rate:'flex'|'nr', promoPct?, rooms?:[ids] }
function priceQuote(args = {}) {
  const { mode = 'full', checkIn, checkOut, rate = 'flex', promoPct = 0, rooms = [] } = args;
  const nights = diffNights(checkIn, checkOut);

  let subtotal = 0;
  let directPct = 0;
  let lineItems = [];

  if (mode === 'full') {
    subtotal = basePriceForRange(checkIn, checkOut);
    directPct = PRICING.directDiscountPct;
    lineItems = [{ key:'full', label:null, qty:nights, subtotal }];
  } else {
    directPct = PRICING.directDiscountRoomPct;
    for (const id of rooms) {
      const sub = roomBasePriceForRange(id, checkIn, checkOut);
      subtotal += sub;
      lineItems.push({ key:'room', roomId:id, qty:nights, subtotal:sub });
    }
  }

  const directDisc  = subtotal * (directPct / 100);
  const afterDirect = subtotal - directDisc;
  const rateDisc    = rate === 'nr' ? afterDirect * (PRICING.nonRefundableExtraPct / 100) : 0;
  const afterRate   = afterDirect - rateDisc;
  const promoDisc   = afterRate * (promoPct / 100);
  const total       = afterRate - promoDisc;

  return {
    mode, subtotal, directPct, directDisc, rateDisc, promoDisc, total, nights,
    perNight: nights ? total / nights : 0,
    lineItems,
  };
}

// -------- min stay validation --------
function violatesMinStay(checkIn, checkOut) {
  const nights = diffNights(checkIn, checkOut);
  if (nights < 1) return false;
  // any weekend night → 2-night min applies for that part. Simplify:
  // if range includes a Fri or Sat night and nights < 2 → violate
  let cur = checkIn, hasWeekend = false;
  while (cur < checkOut) { if (isWeekendNight(cur)) hasWeekend = true; cur = addDays(cur, 1); }
  if (hasWeekend && nights < PRICING.minStayWeekend) return true;
  if (!hasWeekend && nights < PRICING.minStayWeekday) return true;
  return false;
}

// -------- mocked unavailability (for the demo, before Smoobu wiring) --------
// Returns true if range overlaps a fake "blocked" period.
const MOCK_BLOCKED = [
  // Pretend two blocks already taken via Booking
  { from:'2026-05-15', to:'2026-05-18' },
  { from:'2026-06-20', to:'2026-06-24' },
];
function isRangeAvailable(checkIn, checkOut) {
  if (!checkIn || !checkOut) return false;
  for (const b of MOCK_BLOCKED) {
    if (checkIn < b.to && checkOut > b.from) return false;
  }
  return true;
}

// -------- promo codes (mocked) --------
const PROMO_CODES = {
  'CAMINO':   { pct: 5,  label:'Camino de Santiago' },
  'AMIGOS':   { pct: 10, label:'Friends & family' },
  'INVIERNO': { pct: 15, label:'Invierno' },
};
function checkPromo(code) {
  if (!code) return null;
  return PROMO_CODES[code.trim().toUpperCase()] || null;
}

window.BookingEngine = {
  PRICING, ROOMS, getRoom,
  todayISO, toISO, fromISO, addDays, diffNights, isWeekendNight,
  fmtDate, fmtDateLong, fmtMoney,
  basePriceForRange, roomBasePriceForRange, allRoomsBasePriceForRange,
  buildingSavingsVsAllRooms, priceQuote,
  violatesMinStay, isRangeAvailable, checkPromo,
};
