const INTERFACES={CONTACT:0,ADDONS:1,PAYMENT:2};function CheckoutModel(){const e=this;e.focusInterface=ko.observable(INTERFACES.CONTACT),e.isProcessing=ko.observable(!1),e.catalogAddons=ko.observableArray([]),e.hasCatalogAddons=ko.pureComputed(()=>e.catalogAddons().length>0),e.items=ko.observableArray([]),e.rawItems=[],e.hasItems=ko.pureComputed(()=>e.items().length>0),e.itemCountLabel=ko.pureComputed(()=>{const t=e.items().length;return 1===t?"1 room":`${t} rooms`}),e.totalPrice=ko.pureComputed(()=>{const t=e.items().reduce((e,t)=>e+t.totalPrice(),0);return Math.round(100*t)/100}),e.totalOriginalPrice=ko.pureComputed(()=>{const t=e.items().reduce((e,t)=>"function"==typeof t.originalTotalPrice?e+t.originalTotalPrice():e+t.totalPrice(),0);return Math.round(100*t)/100}),e.hasDiscountedTotal=ko.pureComputed(()=>e.totalOriginalPrice()-e.totalPrice()>.009&&e.items().some(e=>"function"==typeof e.hasDiscount&&e.hasDiscount())),e.formatMoney=e=>`${String.fromCharCode(163)}${(Number(e)||0).toFixed(2)}`;const t=(e="")=>String(e??"").replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'"),o=e=>{if(!e||"string"!=typeof e)return null;const t=e.trim().match(/^(\d{4})-(\d{2})-(\d{2})$/);if(!t)return null;const[,o,r,a]=t,n=new Date(Number(o),Number(r)-1,Number(a));return Number.isNaN(n.getTime())?null:n},r=(e,t)=>e?.[t]??e?.[`${t.charAt(0).toUpperCase()}${t.slice(1)}`]??null,a=e=>{if(!(e instanceof Date))return!1;const t=new Date;return t.setHours(0,0,0,0),e{if("string"!=typeof e)return"per_night";return"quantity"===e.trim().toLowerCase()?"quantity":"per_night"};e.setAvailableAddons=(t=[])=>{const o=(t||[]).map(e=>({id:Number(e.id),name:e.name||"",pricePerDay:Math.round(100*(Number(e.pricePerDay)||0))/100,imageUrl:e.imageUrl||null,chargeType:i(e.chargeType)})).filter(e=>Number.isFinite(e.id)&&e.id>0);e.catalogAddons(o),e.rebuildItems()},e.setItems=(t=[])=>{e.rawItems=Array.isArray(t)?t:[],e.rebuildItems()},e.rebuildItems=()=>{const t=e.catalogAddons(),o=e.rawItems.map(o=>e.createItemModel(o,t));e.items(o),e.hasCatalogAddons()||e.focusInterface()!==INTERFACES.ADDONS||e.focusInterface(INTERFACES.CONTACT),e.alertExpiredItems()},e.createItemModel=(t,o)=>{const r=Math.round(100*(Number(t.price)||0))/100,a=Number(t.nights),n=Number.isFinite(a)?Math.max(1,Math.round(a)):1,s=`${n} night${1===n?"":"s"}`,l=Number(t.discountPercent)||0,d=Number(t.originalPrice??t.price),u=Number.isFinite(d)?Math.round(100*d)/100:r,c=Math.round(100*(Number(t.bedSurcharge)||0))/100,m=t.bedTypeLabel||t.bedType||"",p=t.checkin||"",h=t.checkout||"",f=p&&h?`${p} -> ${h}`:"",g=ko.observableArray(Array.isArray(t.legacyAddons)?t.legacyAddons:[]),b=new Map((Array.isArray(t.addons)?t.addons:[]).map(e=>[Number(e.id),e])),y={...t,price:r,nights:n,nightsLabel:s,dateRange:f,bedSurcharge:c,bedTypeLabel:m,legacyAddons:g,addons:[],originalPrice:u,discountPercent:l,isSavingAddons:ko.observable(!1),addonSaveError:ko.observable(null),_addonsPersistTimer:null,_suppressPersist:!1},A=o.map(t=>{const o=b.get(t.id),r=o?Math.max(0,Math.min(10,Math.floor(Number(o.quantity)||0))):0,a=i(t.chargeType),s="per_night"===a,l={id:t.id,name:t.name,pricePerDay:t.pricePerDay,imageUrl:t.imageUrl,chargeType:a,isPerNight:s,quantity:ko.observable(r),nights:n};return l.total=ko.pureComputed(()=>{const e=l.quantity(),o=Math.max(0,Math.min(10,Math.floor(Number(e)||0))),r=l.isPerNight?n:1;return Math.round(o*t.pricePerDay*r*100)/100}),l.unitPriceLabel=ko.pureComputed(()=>l.isPerNight?`${e.formatMoney(t.pricePerDay)} per night`:`${e.formatMoney(t.pricePerDay)} each`),l.detailLine=ko.pureComputed(()=>{const t=Math.max(0,Math.floor(Number(l.quantity())||0)),o=[l.unitPriceLabel()];return o.push(`Qty ${t}`),l.isPerNight&&o.push(`${n} night${1===n?"":"s"}`),o.push(`Total: ${e.formatMoney(l.total())}`),o.join(" • ")}),l.quantityLabel=l.isPerNight?"Qty / night":"Quantity",l.isSelected=ko.pureComputed(()=>l.quantity()>0),l.quantity.subscribe(t=>{const o=Math.max(0,Math.min(10,Math.floor(Number(t)||0)));o===t?y._suppressPersist||e.queuePersistAddons(y):l.quantity(o)}),l});return y.addons=A,y.addonsPerNight=A.filter(e=>e.isPerNight),y.addonsPerStay=A.filter(e=>!e.isPerNight),y.addonsTotal=ko.pureComputed(()=>{const e=A.reduce((e,t)=>e+t.total(),0);return Math.round(100*e)/100}),y.totalPrice=ko.pureComputed(()=>Math.round(100*(r+c+y.addonsTotal()))/100),y.originalTotalPrice=ko.pureComputed(()=>Math.round(100*(u+c+y.addonsTotal()))/100),y.formattedBasePrice=ko.pureComputed(()=>e.formatMoney(r)),y.formattedOriginalBasePrice=ko.pureComputed(()=>e.formatMoney(u)),y.hasBedSurcharge=ko.pureComputed(()=>c>.009),y.formattedBedSurcharge=ko.pureComputed(()=>e.formatMoney(c)),y.formattedAddonsTotal=ko.pureComputed(()=>e.formatMoney(y.addonsTotal())),y.formattedTotalPrice=ko.pureComputed(()=>e.formatMoney(y.totalPrice())),y.formattedOriginalTotalPrice=ko.pureComputed(()=>e.formatMoney(y.originalTotalPrice())),y.hasDiscount=ko.pureComputed(()=>Number(y.discountPercent)>0&&u-r>.009),y},e.queuePersistAddons=t=>{t&&t.id&&(t._addonsPersistTimer&&clearTimeout(t._addonsPersistTimer),t._addonsPersistTimer=setTimeout(()=>{e.persistAddons(t)},300))},e.persistAddons=t=>{if(!t?.id)return;const o=t.addons.map(e=>({id:e.id,quantity:Math.max(0,Math.min(10,Math.floor(Number(e.quantity())||0)))})).filter(e=>e.quantity>0);t.isSavingAddons(!0),t.addonSaveError(null),fetch(`/basket/items/${t.id}/addons`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({addons:o})}).then(e=>e.ok?e.json():e.json().catch(()=>({})).then(e=>{throw e})).then(o=>{const r=Array.isArray(o?.addons)?o.addons:[],a=new Map(r.map(e=>[Number(e.id),e]));t._suppressPersist=!0,t.addons.forEach(e=>{const t=a.get(e.id),o=t?Math.max(0,Math.min(10,Math.floor(Number(t.quantity)||0))):0;e.quantity(o)}),t._suppressPersist=!1,t.legacyAddons([]),e.rawItems=e.rawItems.map(e=>e.id!==t.id?e:{...e,addons:r,legacyAddons:[]})}).catch(e=>{const o="ADDON_UNAVAILABLE"===(e?.status||e?.Status)?"One of the selected add-ons is no longer available. Please review your selection.":e?.message||e?.Message||"We could not update add-ons right now. Please try again.";t.addonSaveError(o),showAlert("fa fa-times","Error",o,"#FFFFFF",!1)}).finally(()=>{t.isSavingAddons(!1),t._addonsPersistTimer=null})},e.removeItem=t=>{t?.id&&!e.isProcessing()&&fetch(`/basket/items/${t.id}`,{method:"DELETE",headers:{"Content-Type":"application/json"}}).then(e=>{if(!e.ok)throw new Error("Failed to remove item");return e.json()}).then(()=>{e.rawItems=e.rawItems.filter(e=>e.id!==t.id),t._addonsPersistTimer&&(clearTimeout(t._addonsPersistTimer),t._addonsPersistTimer=null),e.items.remove(e=>e.id===t.id),e.items().length||e.focusInterface(INTERFACES.CONTACT);Boolean(t?._suppressRemovalAlert)?t._suppressRemovalAlert=!1:showAlert("fa fa-check","Removed","Room removed from your basket.","#FFFFFF",!1),e.alertExpiredItems(!0)}).catch(()=>{t?._suppressRemovalAlert&&(t._suppressRemovalAlert=!1),showAlert("fa fa-times","Error","Could not remove this room. Please try again.","#FFFFFF",!1)})},e.dismissOverlay=()=>{try{document.body.classList.remove("overlay"),window.parent&&window.parent.document&&window.parent.document.body?.classList?.remove?.("overlay")}catch(e){}setTimeout(()=>{const e=document.querySelector(".modalo");e&&!document.body.classList.contains("overlay")&&(e.innerHTML="")},200)},e.removeItemById=(t,o={})=>{const r=Number(t);if(!Number.isFinite(r))return;const a=e.items().find(e=>e.id===r);a&&(o?.suppressAlert&&(a._suppressRemovalAlert=!0),e.removeItem(a))},e.handleExpiredRemove=t=>{e.removeItemById(t,{suppressAlert:!0})},e.alertExpiredItems=(i=!1)=>{const s=e.items().filter(e=>(e=>{const t=o(r(e,"checkout"));if(t)return a(t);const n=o(r(e,"checkin"));return!!n&&a(n)})(e)),l=s.map(e=>Number(e.id)||0).filter(e=>e>0).sort((e,t)=>e-t).join("|");if(!s.length)return e._expiredAlertSignature=null,void(i&&e.dismissOverlay());if(!i&&e._expiredAlertSignature===l)return;e._expiredAlertSignature=l;const d=s.map(e=>{const a=t((e=>e?.Name||e?.name||"Room")(e)),i=t((e=>{const t=o(r(e,"checkin")),a=o(r(e,"checkout"));return t&&a?`${n.format(t)} → ${n.format(a)}`:t?n.format(t):a?n.format(a):"Date unavailable"})(e)),s=(e=>e?.Image||e?.imageUrl||null)(e),l=Number(e.id)||0;return`
\n
${s?`t(e).replace(/`/g,"`"))(s)}" alt="${a}" style="width:100%;height:100%;object-fit:cover;" />`:'
No image
'}
\n
\n

${a}

\n

${i}

\n ${l>0?``:""}\n
\n
`}).join("");showOverlay({Contents:`\n
\n
\n \n

Some stays have expired

\n

These bookings ended before today. Remove them from your basket to continue.

\n
\n
\n ${d}\n
\n
\n \n
\n
\n `,NoExit:!1})},e.nextInterfaceLabel=ko.pureComputed(()=>{const t=e.focusInterface();return t===INTERFACES.CONTACT?e.hasCatalogAddons()?"Continue to Add-ons":"Continue to Payment":t===INTERFACES.ADDONS?"Continue to Payment":"Continue"}),e.nextInterface=()=>{const t=e.focusInterface(),o=Math.max(...Object.values(INTERFACES));if(t===INTERFACES.CONTACT){const t=e.custContact.forename(),o=e.custContact.surname(),r=e.custContact.email(),a=e.custContact.phone();if(!(t?.trim()&&o?.trim()&&r?.trim()&&a?.trim()))return void showAlert("fa fa-times","Error","Please enter all required fields","#FFFFFF",!1)}if(t===INTERFACES.ADDONS){if(e.items().some(e=>e.legacyAddons().length>0))return void showAlert("fa fa-times","Review add-ons","Some add-ons are no longer available. Please adjust the quantities before continuing.","#FFFFFF",!1);if(e.items().some(e=>e.isSavingAddons()))return void showAlert("fa fa-clock-o","Please wait","We are saving your add-on changes. This will only take a moment.","#FFFFFF",!1)}let r=t+1;r!==INTERFACES.ADDONS||e.hasCatalogAddons()||(r+=1),r<=o&&e.focusInterface(r)},e.custContact=new CustContactModel,e.billingDetails=new BillingDetailsModel,e.billingCountryOptions=[{label:"United Kingdom (GB)",value:"GB"},{label:"Ireland (IE)",value:"IE"},{label:"United States (US)",value:"US"},{label:"Canada (CA)",value:"CA"},{label:"Australia (AU)",value:"AU"},{label:"New Zealand (NZ)",value:"NZ"},{label:"France (FR)",value:"FR"},{label:"Germany (DE)",value:"DE"},{label:"Spain (ES)",value:"ES"},{label:"Italy (IT)",value:"IT"}],e.checkoutProcess=()=>{if(e.isProcessing())return;if(!e.hasItems())return void showAlert("fa fa-times","Error","Your basket is empty. Please add a room before checking out.","#FFFFFF",!1);const t=e.custContact.forename(),o=e.custContact.surname(),r=e.custContact.email(),a=e.custContact.phone(),n=e.custContact.country(),i=e.custContact.comments();if(!(t?.trim()&&o?.trim()&&r?.trim()&&a?.trim()))return showAlert("fa fa-times","Error","Please enter all required fields","#FFFFFF",!1),void e.focusInterface(INTERFACES.CONTACT);e.isProcessing(!0);const s={custContact:{forename:t,surname:o,email:r,phone:a,country:n,comments:i},policyAccept:!0,billingDetails:{forename:e.billingDetails.forename(),surname:e.billingDetails.surname(),addressLine1:e.billingDetails.addressLine1(),addressLine2:e.billingDetails.addressLine2(),addressLine3:e.billingDetails.addressLine3(),addressLine4:e.billingDetails.addressLine4(),postcode:e.billingDetails.postcode(),country:e.billingDetails.country()}};fetch("/book-in",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}).then(e=>e.ok?e.json():e.json().catch(()=>({})).then(e=>{throw e})).then(t=>{t.redirectURL?window.location.href=t.redirectURL:(e.isProcessing(!1),showAlert("fa fa-times","Error","No payment link returned. Please try again.","#FFFFFF",!1))}).catch(t=>{e.isProcessing(!1);const o={EMPTY_BASKET:"Your basket is empty. Please add a room before checking out.",CONTACT_REQUIRED:"Please complete the required contact details.",POLICY_NOT_ACCEPTED:"Please accept the terms before continuing.",ROOM_UNAVAILABLE:"One of your rooms is no longer available. Please review your basket.",ROOM_NOT_FOUND:"We could not find one of the rooms in your basket. Please refresh and try again.",INVALID_PRICE:"We were unable to confirm the room price. Please refresh the page and try again.",SESSION_SAVE_FAILED:"We could not save your basket. Please try again in a moment.",ADDON_UNAVAILABLE:"One of your selected add-ons is no longer available. Please review your basket.",INVALID_BED_OPTION:"A selected bed setup is no longer available. Please review your basket.",BOOKING_FAILED:"We could not create your booking. Please try again in a moment."},r=t?.Status&&o[t.Status]?o[t.Status]:"Something went wrong while starting the checkout. Please try again.";showAlert("fa fa-times","Error",r,"#FFFFFF",!1)})}}function CustContactModel(){const e=this;e.forename=ko.observable(),e.surname=ko.observable(),e.email=ko.observable(),e.phone=ko.observable(),e.country=ko.observable("United Kingdom"),e.comments=ko.observable()}function BillingDetailsModel(){const e=this;e.forename=ko.observable(""),e.surname=ko.observable(""),e.addressLine1=ko.observable(""),e.addressLine2=ko.observable(""),e.addressLine3=ko.observable(""),e.addressLine4=ko.observable(""),e.postcode=ko.observable(""),e.country=ko.observable("GB")}const checkoutModel=new CheckoutModel;document.addEventListener("DOMContentLoaded",()=>{ko.applyBindings(checkoutModel,document.getElementById("root"))}),window.checkoutModel=checkoutModel;