"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EPaymentMethod = void 0;
const BaseAPI_1 = __importStar(require("./BaseAPI"));
var EPaymentMethod;
(function (EPaymentMethod) {
    EPaymentMethod["PLANPAY"] = "Planpay";
    EPaymentMethod["CARD"] = "Card";
})(EPaymentMethod || (exports.EPaymentMethod = EPaymentMethod = {}));
class ReservationAPI extends BaseAPI_1.default {
    constructor() {
        super(...arguments);
        this.storedReservations = {};
        /**
         * Populates a booking quote request.
         */
        this.buildQuoteRequest = (rows, memberNumber) => {
            const quoteRows = rows.reduce((acc, row) => {
                var _a;
                try {
                    acc.push({
                        rowId: row.getID(),
                        roomCode: row.getRoom().code,
                        rateCode: (_a = row.getRate()) === null || _a === void 0 ? void 0 : _a.code,
                        promoCode: row.getPromoCode(),
                        adults: row.getAdults(),
                        children: row.getChildren(),
                        infants: row.getInfants(),
                        checkIn: row.getStartDate().format('YYYY-MM-DD'),
                        checkOut: row.getEndDate().format('YYYY-MM-DD'),
                        memberNumber,
                        totalDisplayedPrice: row.getTotalPrice(),
                    });
                }
                catch (ex) {
                    // Skip row if it throws
                    // Fixed: The checkout step will hang indefinitely if any basket row is missing a selected room rate
                }
                return acc;
            }, []);
            return { rows: quoteRows };
        };
        /**
         * Populates a pencil reservation request based on a quote request.
         */
        this.buildPencilRequest = (rows, memberNumber, pencilId) => {
            const quoteRequest = this.buildQuoteRequest(rows, memberNumber);
            const pencilRequest = Object.assign(Object.assign({}, quoteRequest), { pencilId: pencilId });
            pencilRequest.rows = quoteRequest.rows.map((requestRow) => {
                const basketRow = rows.find((r) => r.getID() == requestRow.rowId);
                return Object.assign(Object.assign({}, requestRow), { pencilId: basketRow === null || basketRow === void 0 ? void 0 : basketRow.pencilId });
            });
            return pencilRequest;
        };
        /**
         * Generates a unique query ID string based on basket row data.
         * This ID is used to detect changes and re-fetch deposit quotes during checkout.
         */
        this.buildQuoteQueryID = (rows, memberNumber) => {
            return rows
                .map((row) => {
                var _a, _b, _c, _d;
                return `row:${row.getID()},
                    room:${(_a = row.getRoom()) === null || _a === void 0 ? void 0 : _a.code},
                    rate:${(_b = row.getRate()) === null || _b === void 0 ? void 0 : _b.code},
                    promo:${row.getPromoCode()},
                    adults:${row.getAdults()},
                    children:${row.getChildren()},
                    infants:${row.getInfants()},
                    checkIn:${(_c = row.getStartDate()) === null || _c === void 0 ? void 0 : _c.format('YYYY-MM-DD')},
                    checkOut:${(_d = row.getEndDate()) === null || _d === void 0 ? void 0 : _d.format('YYYY-MM-DD')},
                    member:${memberNumber}`;
            })
                .join('-');
        };
        /**
         * Returns a quote for the given
         */
        this.getPriceQuote = (hotelId, rows, memberNumber) => __awaiter(this, void 0, void 0, function* () {
            const quoteBody = this.buildQuoteRequest(rows, memberNumber);
            return this.post(BaseAPI_1.APIEndpoint.Reservations, quoteBody, hotelId, {}, 'quote');
        });
        /**
         * Pencils a reservation for the given rooms. Returns the timeout, and quote if applicable.
         */
        this.pencilReservation = (hotelId, rows, memberNumber, pencilId) => __awaiter(this, void 0, void 0, function* () {
            const quoteBody = this.buildPencilRequest(rows, memberNumber, pencilId);
            return this.post(BaseAPI_1.APIEndpoint.Reservations, quoteBody, hotelId, {}, 'pencil');
        });
        /**
         *
         * @param basketRows
         * @param userProfiles
         * @param payment
         * @param addonRows
         * @param comments
         * @param hotelId
         * @param sessionId
         * @param specialReq
         * @returns
         */
        this.bookNow = (basketRows_1, userProfiles_1, payment_1, addonRows_1, comments_1, hotelId_1, sessionId_1, ...args_1) => __awaiter(this, [basketRows_1, userProfiles_1, payment_1, addonRows_1, comments_1, hotelId_1, sessionId_1, ...args_1], void 0, function* (basketRows, userProfiles, payment, addonRows, comments, hotelId, sessionId, pencilId = undefined, specialReq = undefined, retryPayment = false, roomstayId = undefined, memberNumber = undefined, giftCardPreauth = undefined, extraFields) {
            var _a;
            const rooms = [];
            basketRows.forEach((row) => {
                var _a, _b;
                const room = {
                    roomType: row.getRoom().code || '',
                    ratePlan: ((_a = row.getRate()) === null || _a === void 0 ? void 0 : _a.code) || '',
                    promoCode: row.getPromoCode(),
                    adults: row.getAdults(),
                    children: row.getChildren(),
                    infants: row.getInfants(),
                    checkInDate: row.getStartDate().format('YYYY-MM-DD'),
                    checkOutDate: row.getEndDate().format('YYYY-MM-DD'),
                    quoteId: (_b = row.quoteDetails) === null || _b === void 0 ? void 0 : _b.quoteId,
                    rowId: row.getID(),
                    memberNumber,
                    pencilId: row.pencilId,
                };
                rooms.push(room);
            });
            const addons = addonRows.map((row) => {
                const addon = row.getAddon();
                const priceInfo = addon.availability[row.getSelectedDate()];
                const response = {
                    code: addon.code,
                    startDate: row.getSelectedDate(),
                };
                if (addon === null || addon === void 0 ? void 0 : addon.ratePlanCode) {
                    response.ratePlanCode = row.getAddon().ratePlanCode;
                }
                if (row.getSelectedTime()) {
                    response.startTime = row.getSelectedTime();
                }
                if (priceInfo.price) {
                    response.quantity = row.getQuantity();
                }
                if (priceInfo.adultPrice) {
                    response.adults = row.getAdultQuantity();
                }
                if (priceInfo.childPrice) {
                    response.children = row.getChildQuantity();
                }
                if (addon.pricingType) {
                    response.pricingType = addon.pricingType;
                }
                return response;
            });
            const getParams = {};
            if (retryPayment) {
                getParams.retryPayment = true;
            }
            const requestBody = {
                rooms: rooms,
                services: addons,
                specialRequest: specialReq,
                comments: comments,
                profiles: userProfiles,
                payment: payment,
                sessionId: sessionId,
                pencilId: pencilId,
                sourceUrl: window.location.href,
                roomstayId: roomstayId,
                extraFields,
            };
            // Add gift card preauth details if necessary
            if (giftCardPreauth) {
                requestBody.giftCard = {
                    token: giftCardPreauth.token,
                    code: ((_a = giftCardPreauth.giftCard) === null || _a === void 0 ? void 0 : _a.code) || '',
                    transactionId: giftCardPreauth.id,
                };
            }
            return this.post(BaseAPI_1.APIEndpoint.Reservations, requestBody, hotelId, getParams);
        });
        this.commit = (reservations, itineraryId, hotelId, planpayCheckoutId, paymentId) => __awaiter(this, void 0, void 0, function* () {
            return this.post(BaseAPI_1.APIEndpoint.Reservations, {
                itineraryId: itineraryId,
                reservationIds: reservations,
                planpayCheckoutId,
                paymentId,
            }, hotelId, {}, 'commit');
        });
        this.rollback = (reservations, itineraryId, hotelId) => __awaiter(this, void 0, void 0, function* () {
            yield this.post(BaseAPI_1.APIEndpoint.Reservations, {
                itineraryId: itineraryId,
                reservationIds: reservations,
            }, hotelId, {}, 'rollback');
            return true;
        });
        this.cancelReservation = (id, email, hotelId) => new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
            var _a, _b;
            try {
                const response = yield this.delete(BaseAPI_1.APIEndpoint.Reservations, {}, hotelId, { email }, id);
                (_b = (_a = this.storedReservations[id]) === null || _a === void 0 ? void 0 : _a.reservations) === null || _b === void 0 ? void 0 : _b.forEach((reservation) => {
                    if (reservation.reservationNumber === id) {
                        reservation.status = 'Cancelled';
                    }
                });
                resolve(response);
            }
            catch (ex) {
                reject(ex);
            }
        }));
        this.findReservation = (id, email, hotelId) => new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
            /*
      resolve with locally cached data, so we don't have to re-query this again
  */
            if (this.storedReservations[id]) {
                return resolve(this.storedReservations[id]);
            }
            try {
                const response = yield this.get(BaseAPI_1.APIEndpoint.Reservations, { email }, id, hotelId);
                this.storedReservations[id] = response;
                resolve(response);
            }
            catch (ex) {
                reject(ex);
            }
        }));
        this.linkBookingToMember = (hotelId, reservationId, reservationEmail) => __awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
                try {
                    const response = yield this.post(BaseAPI_1.APIEndpoint.Reservations, {
                        reservationId,
                        reservationEmail,
                    }, hotelId, {}, 'link-booking');
                    resolve(response);
                }
                catch (ex) {
                    reject(ex);
                }
            }));
        });
    }
}
exports.default = ReservationAPI;
//# sourceMappingURL=ReservationAPI.js.map