const axios = require("axios");
const xml2js = require("xml2js");

const HOTEL_URL = process.env.TRAVELPORT_HOTEL_SERVICE;
const USERNAME = process.env.TRAVELPORT_USERNAME;
const PASSWORD = process.env.TRAVELPORT_PASSWORD;
const TARGET_BRANCH = process.env.TARGET_BRANCH;
const PROVIDER = process.env.PROVIDER_CODE || "1G";

const authorizedBy = process.env.TRAVELPORT_USERNAME.replace(/[^a-zA-Z0-9]/g, "");

exports.searchHotels = async (data) => {

  console.log("====================================");
  console.log("HOTEL SEARCH SERVICE START");
  console.log("INPUT DATA:", JSON.stringify(data, null, 2));
  console.log("====================================");

  try {

    const {
      cityCode,
      location,
      checkinDate,
      checkoutDate,
      adults = 1,
      rooms = 1,
      availableHotelsOnly = false,
      returnAmenities = false,
    } = data;

    const finalCityCode = (cityCode || location || "").toUpperCase();

    if (!finalCityCode) throw new Error("cityCode or location is required");
    if (!checkinDate || !checkoutDate) throw new Error("checkinDate and checkoutDate are required");

    /* -----------------------------------
       BUILD SOAP BODY
    ----------------------------------- */

    const buildSoapBody = (nextResultReference = null) => {

      const nextRefXML = nextResultReference
        ? `<com:NextResultReference ProviderCode="${PROVIDER}">${nextResultReference}</com:NextResultReference>`
        : "";

      return `
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<hot:HotelSearchAvailabilityReq
  AuthorizedBy="${authorizedBy}"
  TargetBranch="${TARGET_BRANCH}"
  TraceId="TRACE_${Date.now()}"
  xmlns:hot="http://www.travelport.com/schema/hotel_v54_0"
  xmlns:com="http://www.travelport.com/schema/common_v54_0">

  <com:BillingPointOfSaleInfo OriginApplication="UAPI"/>
  ${nextRefXML}

  <hot:HotelSearchLocation>
    <hot:HotelLocation Location="${finalCityCode}" LocationType="City"/>
  </hot:HotelSearchLocation>

  <hot:HotelSearchModifiers
    NumberOfAdults="${Number(adults)}"
    NumberOfRooms="${rooms}"
    AvailableHotelsOnly="${availableHotelsOnly}"
    ReturnAmenities="${returnAmenities}"
    ReturnProviderHotelDetails="true"/>

  <hot:HotelStay>
    <hot:CheckinDate>${checkinDate}</hot:CheckinDate>
    <hot:CheckoutDate>${checkoutDate}</hot:CheckoutDate>
  </hot:HotelStay>

</hot:HotelSearchAvailabilityReq>
</soapenv:Body>
</soapenv:Envelope>`;
    };

    /* -----------------------------------
       SOAP CALL HELPER
    ----------------------------------- */

    const callSoap = async (body) => {
      const response = await axios.post(HOTEL_URL, body, {
        headers: { "Content-Type": "text/xml;charset=UTF-8" },
        auth: { username: USERNAME, password: PASSWORD },
        timeout: 60000,
        maxBodyLength: Infinity,
        maxContentLength: Infinity
      });

      const parser = new xml2js.Parser({ explicitArray: false, ignoreAttrs: false });
      return parser.parseStringPromise(response.data);
    };

    /* -----------------------------------
       FETCH ALL PAGES — collect raw results
    ----------------------------------- */

    let allResults = [];
    let nextRef = null;
    let pageCount = 0;
    const MAX_PAGES = 5;

    do {
      const parsed = await callSoap(buildSoapBody(nextRef));

      const body = parsed?.["SOAP:Envelope"]?.["SOAP:Body"];

      if (body?.["SOAP:Fault"]) {
        console.log("SOAP FAULT:", JSON.stringify(body["SOAP:Fault"], null, 2));
        break;
      }

      const rsp = body?.["hotel:HotelSearchAvailabilityRsp"];
      if (!rsp) break;

      // ✅ Collect raw HotelSearchResult array as-is
      const results = rsp?.["hotel:HotelSearchResult"] || [];
      const resultList = Array.isArray(results) ? results : [results];

      // ✅ Only include results that have RateInfo (have actual prices)
      const withRates = resultList.filter(r => r?.["hotel:RateInfo"]);

      allResults = allResults.concat(withRates);

      const nextRefNode = rsp?.["common_v54_0:NextResultReference"];
      nextRef = nextRefNode?._ || null;

      pageCount++;

      console.log(`PAGE ${pageCount}: Got ${resultList.length} total, ${withRates.length} with rates. NextRef: ${nextRef ? "YES" : "NO"}`);

    } while (nextRef && pageCount < MAX_PAGES);

    console.log(`TOTAL RESULTS WITH RATES: ${allResults.length}`);

    return {
      totalResults: allResults.length,
      hotelSearchResults: allResults
    };

  } catch (error) {
    console.error("HOTEL SEARCH SERVICE ERROR:", error.message);
    throw error;
  }
};