"use strict";
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());
    });
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _a, _MitraPackageService_calculateTotal;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MitraPackageService = void 0;
const uuid_1 = require("uuid");
const database_1 = require("../application/database");
const response_error_1 = require("../error/response-error");
const mitra_package_validation_1 = require("../validation/mitra-package-validation");
const validation_1 = require("../validation/validation");
class MitraPackageService {
    static create(request) {
        return __awaiter(this, void 0, void 0, function* () {
            // Validate the create request
            const createRequest = validation_1.Validation.validate(mitra_package_validation_1.MitraPackageValidation.CREATE, request);
            // Calculate the total price for each room type
            const { double, triple, quad } = yield __classPrivateFieldGet(_a, _a, "m", _MitraPackageService_calculateTotal).call(_a, createRequest);
            // Generate a UUID for the new mitra package
            const mitraPackageId = (0, uuid_1.v4)();
            // Insert the new mitra package into the database
            yield database_1.db.query(`
      INSERT INTO mitra_package (
        id,
        period_id,
        airline_id,
        vendor_id,
        hotel_mekkah_id,
        hotel_madinah_id,
        visa_id,
        transportation_id,
        muthawif_id,
        handling_saudi_id,
        handling_domestic_id,
        siskopatuh_id,
        equipment_id,
        tour_plus_id,
        manasik_id,
        number_of_pax,
        departure_date,
        travel_duration,
        mekkah_duration,
        madinah_duration,
        tour_leader,
        margin,
        per_pax_price_double,
        per_pax_price_triple,
        per_pax_price_quad
      ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
    `, [
                mitraPackageId,
                createRequest.period_id,
                createRequest.airline_id,
                createRequest.vendor_id,
                createRequest.hotel_mekkah_id,
                createRequest.hotel_madinah_id,
                createRequest.visa_id,
                createRequest.transportation_id,
                createRequest.muthawif_id,
                createRequest.handling_saudi_id,
                createRequest.handling_domestic_id,
                createRequest.siskopatuh_id,
                createRequest.equipment_id,
                createRequest.tour_plus_id,
                createRequest.manasik_id,
                createRequest.number_of_pax,
                createRequest.departure_date,
                createRequest.travel_duration,
                createRequest.mekkah_duration,
                createRequest.madinah_duration,
                createRequest.tour_leader,
                createRequest.margin,
                double,
                triple,
                quad,
            ]);
            return mitraPackageId;
        });
    }
    static get(id) {
        return __awaiter(this, void 0, void 0, function* () {
            // Fetch the main mitra package and related details
            const mitraPackage = yield database_1.db.queryOne(`
      SELECT mp.*, p.*, 
        a.name AS airline_name, a.price_idr AS airline_price_idr, 
        v.name AS vendor_name,
        vi.name AS visa_name, vi.price_idr AS visa_price_idr,
        t.name AS transportation_name, t.price_idr AS transportation_price_idr,
        m.name AS muthawif_name, m.price_idr AS muthawif_price_idr,
        hs.name AS handling_saudi_name, hs.price_idr AS handling_saudi_price_idr,
        hd.name AS handling_domestic_name, hd.price_idr AS handling_domestic_price_idr,
        s.name AS siskopatuh_name, s.price_idr AS siskopatuh_price_idr,
        e.name AS equipment_name, e.price_idr AS equipment_price_idr,
        tp.name AS tour_plus_name, tp.price_idr AS tour_plus_price_idr,
        ma.name AS manasik_name, ma.price_idr AS manasik_price_idr
      FROM mitra_package mp
      LEFT JOIN period p ON mp.period_id = p.id
      LEFT JOIN airline a ON mp.airline_id = a.id
      LEFT JOIN vendor v ON mp.vendor_id = v.id
      LEFT JOIN visa vi ON mp.visa_id = vi.id
      LEFT JOIN transportation t ON mp.transportation_id = t.id
      LEFT JOIN muthawif m ON mp.muthawif_id = m.id
      LEFT JOIN handling_saudi hs ON mp.handling_saudi_id = hs.id
      LEFT JOIN handling_domestic hd ON mp.handling_domestic_id = hd.id
      LEFT JOIN siskopatuh s ON mp.siskopatuh_id = s.id
      LEFT JOIN equipment e ON mp.equipment_id = e.id
      LEFT JOIN tour_plus tp ON mp.tour_plus_id = tp.id
      LEFT JOIN manasik ma ON mp.manasik_id = ma.id
      WHERE mp.id = ?
      `, [id]);
            if (!mitraPackage) {
                throw new response_error_1.ResponseError(404, 'Mitra package not found');
            }
            // Fetch the Mekkah hotel prices for the current period
            const hotelMekkah = yield database_1.db.queryOne(`
      SELECT h.name AS hotel_name, hpp.price_double, hpp.price_triple, hpp.price_quad
      FROM hotel h
      LEFT JOIN hotel_period_price hpp ON h.id = hpp.hotel_id
      WHERE h.id = ? AND hpp.period_id = ?
      LIMIT 1
      `, [mitraPackage.hotel_mekkah_id, mitraPackage.period_id]);
            // Fetch the Madinah hotel prices for the current period
            const hotelMadinah = yield database_1.db.queryOne(`
      SELECT h.name AS hotel_name, hpp.price_double, hpp.price_triple, hpp.price_quad
      FROM hotel h
      LEFT JOIN hotel_period_price hpp ON h.id = hpp.hotel_id
      WHERE h.id = ? AND hpp.period_id = ?
      LIMIT 1
      `, [mitraPackage.hotel_madinah_id, mitraPackage.period_id]);
            // Return the structured response directly from the service
            return {
                id: mitraPackage.id,
                number_of_pax: mitraPackage.number_of_pax,
                period: {
                    name: mitraPackage.name,
                    start_date: mitraPackage.start_date,
                    end_date: mitraPackage.end_date,
                },
                departure_date: mitraPackage.departure_date,
                travel_duration: mitraPackage.travel_duration,
                mekkah_duration: mitraPackage.mekkah_duration,
                madinah_duration: mitraPackage.madinah_duration,
                airline: {
                    name: mitraPackage.airline_name,
                    price_idr: mitraPackage.airline_price_idr,
                },
                vendor: {
                    name: mitraPackage.vendor_name,
                    price_idr: mitraPackage.vendor_price_idr,
                },
                hotel_mekkah: {
                    name: hotelMekkah === null || hotelMekkah === void 0 ? void 0 : hotelMekkah.hotel_name,
                    price_double: hotelMekkah === null || hotelMekkah === void 0 ? void 0 : hotelMekkah.price_double,
                    price_triple: hotelMekkah === null || hotelMekkah === void 0 ? void 0 : hotelMekkah.price_triple,
                    price_quad: hotelMekkah === null || hotelMekkah === void 0 ? void 0 : hotelMekkah.price_quad,
                },
                hotel_madinah: {
                    name: hotelMadinah === null || hotelMadinah === void 0 ? void 0 : hotelMadinah.hotel_name,
                    price_double: hotelMadinah === null || hotelMadinah === void 0 ? void 0 : hotelMadinah.price_double,
                    price_triple: hotelMadinah === null || hotelMadinah === void 0 ? void 0 : hotelMadinah.price_triple,
                    price_quad: hotelMadinah === null || hotelMadinah === void 0 ? void 0 : hotelMadinah.price_quad,
                },
                visa: {
                    name: mitraPackage.visa_name,
                    price_idr: mitraPackage.visa_price_idr,
                },
                transportation: {
                    name: mitraPackage.transportation_name,
                    price_idr: mitraPackage.transportation_price_idr,
                },
                muthawif: {
                    name: mitraPackage.muthawif_name,
                    price_idr: mitraPackage.muthawif_price_idr,
                },
                handling_saudi: {
                    name: mitraPackage.handling_saudi_name,
                    price_idr: mitraPackage.handling_saudi_price_idr,
                },
                handling_domestic: {
                    name: mitraPackage.handling_domestic_name,
                    price_idr: mitraPackage.handling_domestic_price_idr,
                },
                siskopatuh: {
                    name: mitraPackage.siskopatuh_name,
                    price_idr: mitraPackage.siskopatuh_price_idr,
                },
                equipment: {
                    name: mitraPackage.equipment_name,
                    price_idr: mitraPackage.equipment_price_idr,
                },
                tour_plus: {
                    name: mitraPackage.tour_plus_name,
                    price_idr: mitraPackage.tour_plus_price_idr,
                },
                manasik: {
                    name: mitraPackage.manasik_name,
                    price_idr: mitraPackage.manasik_price_idr,
                },
                tour_leader: mitraPackage.tour_leader,
                margin: mitraPackage.margin,
                per_pax_price_double: mitraPackage.per_pax_price_double,
                per_pax_price_triple: mitraPackage.per_pax_price_triple,
                per_pax_price_quad: mitraPackage.per_pax_price_quad,
            };
        });
    }
}
exports.MitraPackageService = MitraPackageService;
_a = MitraPackageService, _MitraPackageService_calculateTotal = function _MitraPackageService_calculateTotal(request) {
    return __awaiter(this, void 0, void 0, function* () {
        // Fetch the exchange rate
        const SARtoIDR = yield database_1.db.queryOne('SELECT rate_idr FROM exchange_rate WHERE currency = ? LIMIT 1', ['SAR']);
        // const exchangeRate = SARtoIDR ? SARtoIDR.rate_idr : new Prisma.Decimal(1);
        const exchangeRate = (SARtoIDR === null || SARtoIDR === void 0 ? void 0 : SARtoIDR.rate_idr) || 1;
        // Fetch the airline price
        const airline = yield database_1.db.queryOne('SELECT price_idr FROM airline WHERE id = ? LIMIT 1', [request.airline_id]);
        // Fetch the visa price
        const visa = yield database_1.db.queryOne('SELECT price_idr FROM visa WHERE id = ? LIMIT 1', [request.visa_id]);
        // Fetch the transportation price
        const transportation = yield database_1.db.queryOne('SELECT price_idr FROM transportation WHERE id = ? LIMIT 1', [
            request.transportation_id,
        ]);
        // Fetch hotel prices for Mekkah and Madinah
        const hotelMekkah = yield database_1.db.queryOne('SELECT price_double, price_triple, price_quad FROM hotel_period_price WHERE hotel_id = ? AND period_id = ? LIMIT 1', [request.hotel_mekkah_id, request.period_id]);
        const hotelMekkahDouble = (((hotelMekkah === null || hotelMekkah === void 0 ? void 0 : hotelMekkah.price_double) || 0) * Number(exchangeRate) * Number(request.mekkah_duration)) / 2;
        const hotelMekkahTriple = (((hotelMekkah === null || hotelMekkah === void 0 ? void 0 : hotelMekkah.price_triple) || 0) * Number(exchangeRate) * Number(request.mekkah_duration)) / 3;
        const hotelMekkahQuad = (((hotelMekkah === null || hotelMekkah === void 0 ? void 0 : hotelMekkah.price_quad) || 0) * Number(exchangeRate) * Number(request.mekkah_duration)) / 4;
        const hotelMadinah = yield database_1.db.queryOne('SELECT price_double, price_triple, price_quad FROM hotel_period_price WHERE hotel_id = ? AND period_id = ? LIMIT 1', [request.hotel_madinah_id, request.period_id]);
        const hotelMadinahDouble = (((hotelMadinah === null || hotelMadinah === void 0 ? void 0 : hotelMadinah.price_double) || 0) * Number(exchangeRate) * Number(request.madinah_duration)) / 2;
        const hotelMadinahTriple = (((hotelMadinah === null || hotelMadinah === void 0 ? void 0 : hotelMadinah.price_triple) || 0) * Number(exchangeRate) * Number(request.madinah_duration)) / 3;
        const hotelMadinahQuad = (((hotelMadinah === null || hotelMadinah === void 0 ? void 0 : hotelMadinah.price_quad) || 0) * Number(exchangeRate) * Number(request.madinah_duration)) / 4;
        // Fetch the muthawif price
        const muthawif = yield database_1.db.queryOne('SELECT price_idr FROM muthawif WHERE id = ? LIMIT 1', [
            request.muthawif_id,
        ]);
        // Fetch the handling saudi price
        const handlingSaudi = yield database_1.db.queryOne('SELECT price_idr FROM handling_saudi WHERE id = ? LIMIT 1', [
            request.handling_saudi_id,
        ]);
        // Fetch the handling domestic price
        const handlingDomestic = yield database_1.db.queryOne('SELECT price_idr FROM handling_domestic WHERE id = ? LIMIT 1', [
            request.handling_domestic_id,
        ]);
        // Fetch the siskopatuh price
        const siskopatuh = yield database_1.db.queryOne('SELECT price_idr FROM siskopatuh WHERE id = ? LIMIT 1', [
            request.siskopatuh_id,
        ]);
        // Fetch the equipment price
        const equipment = yield database_1.db.queryOne('SELECT price_idr FROM equipment WHERE id = ? LIMIT 1', [
            request.equipment_id,
        ]);
        // Fetch the tour plus price
        const tourPlus = yield database_1.db.queryOne('SELECT price_idr FROM tour_plus WHERE id = ? LIMIT 1', [
            request.tour_plus_id,
        ]);
        // Fetch the manasik price
        const manasik = yield database_1.db.queryOne('SELECT price_idr FROM manasik WHERE id = ? LIMIT 1', [request.manasik_id]);
        // Sum all the prices, using JavaScript numbers
        const totalPrice = Number((airline === null || airline === void 0 ? void 0 : airline.price_idr) || 0) +
            Number((visa === null || visa === void 0 ? void 0 : visa.price_idr) || 0) +
            Number((transportation === null || transportation === void 0 ? void 0 : transportation.price_idr) || 0) +
            Number((muthawif === null || muthawif === void 0 ? void 0 : muthawif.price_idr) || 0) +
            Number((handlingSaudi === null || handlingSaudi === void 0 ? void 0 : handlingSaudi.price_idr) || 0) +
            Number((handlingDomestic === null || handlingDomestic === void 0 ? void 0 : handlingDomestic.price_idr) || 0) +
            Number((siskopatuh === null || siskopatuh === void 0 ? void 0 : siskopatuh.price_idr) || 0) +
            Number((equipment === null || equipment === void 0 ? void 0 : equipment.price_idr) || 0) +
            Number((tourPlus === null || tourPlus === void 0 ? void 0 : tourPlus.price_idr) || 0) +
            Number((manasik === null || manasik === void 0 ? void 0 : manasik.price_idr) || 0);
        // Apply multipliers and tour leader prices
        const paxMultiplier = request.number_of_pax > 0 ? request.number_of_pax : 1;
        const tourLeaderMultiplier = request.tour_leader > 0 ? request.tour_leader : 1;
        // Calculate total prices for each accommodation type
        const totalPriceDouble = totalPrice + hotelMekkahDouble + hotelMadinahDouble;
        const totalPriceTriple = totalPrice + hotelMekkahTriple + hotelMadinahTriple;
        const totalPriceQuad = totalPrice + hotelMekkahQuad + hotelMadinahQuad;
        return {
            double: totalPriceDouble * (1 + tourLeaderMultiplier / paxMultiplier) + request.margin,
            triple: totalPriceTriple * (1 + tourLeaderMultiplier / paxMultiplier) + request.margin,
            quad: totalPriceQuad * (1 + tourLeaderMultiplier / paxMultiplier) + request.margin,
        };
    });
};
