//const { fetchHotelDetails } = require('../services/hotelRateRuleService');
const { fetchHotelRateAndRule } = require('../services/hotelRateRuleService');

/**
 * Controller to handle Hotel Rate & Rule Search
 */
/*const hotelRateRule = async (req, res) => {
  try {
    console.log('Received HotelDetailsReq:', req.body);

    const {
      hotelChain,
      hotelCode,
      checkinDate,
      checkoutDate,
      numberOfAdults,
      returnMediaLinks,
      returnGuestReviews,
      policyReference,
    } = req.body;

    if (!hotelChain || !hotelCode || !checkinDate || !checkoutDate) {
      return res.status(400).json({
        status: 'error',
        message: 'hotelChain, hotelCode, checkinDate, checkoutDate are required'
      });
    }

    const hotelDetails = await fetchHotelDetails({
      hotelChain,
      hotelCode,
      checkinDate,
      checkoutDate,
      numberOfAdults,
      returnMediaLinks,
      returnGuestReviews,
      policyReference,
    });

    res.json({ status: 'success', data: hotelDetails });
  } catch (err) {
    console.error('Controller Error:', err.message);
    res.status(500).json({ status: 'error', message: err.message });
  }
};

module.exports = {
  hotelRateRule*/
  
  exports.getHotelRateAndRule = async (req, res) => {
  console.log("==================================================");
  console.log("CONTROLLER: HotelRateAndRuleReq - START");
  console.log("➡️ Request Body:");
  console.log(JSON.stringify(req.body, null, 2));

  try {
    const { hotelProperty, modifiers, requestOptions } = req.body;

    /* ------------------------------------------------
       LEVEL 1 — Validate required top-level objects
    ------------------------------------------------ */
    if (!hotelProperty) {
      return res.status(400).json({
        success: false,
        message: "hotelProperty is required",
      });
    }

    if (!modifiers) {
      return res.status(400).json({
        success: false,
        message: "modifiers is required (must include checkin, checkout, numberOfAdults)",
      });
    }

    /* ------------------------------------------------
       LEVEL 2 — Validate required HotelProperty attributes
       XSD: HotelChain use="required", HotelCode use="required"
    ------------------------------------------------ */
    if (!hotelProperty.hotelChain) {
      return res.status(400).json({
        success: false,
        message: "hotelProperty.hotelChain is required (2-letter chain code e.g. 'LC', 'WI')",
      });
    }

    if (!hotelProperty.hotelCode) {
      return res.status(400).json({
        success: false,
        message: "hotelProperty.hotelCode is required (hotel property code e.g. '16401')",
      });
    }

    /* ------------------------------------------------
       LEVEL 3 — Validate required modifiers fields
       XSD: CheckinDate + CheckoutDate required in HotelStay
            NumberOfAdults required in HotelRateAndRuleModifiers
    ------------------------------------------------ */
    /*if (!modifiers.checkin) {
      return res.status(400).json({
        success: false,
        message: "modifiers.checkin is required (HotelStay > CheckinDate)",
      });
    }

    if (!modifiers.checkout) {
      return res.status(400).json({
        success: false,
        message: "modifiers.checkout is required (HotelStay > CheckoutDate)",
      });
    }

    if (!modifiers.numberOfAdults) {
      return res.status(400).json({
        success: false,
        message: "modifiers.numberOfAdults is required (minimum 1)",
      });
    }*/

      /* ------------------------------------------------
   LEVEL 3 — Validate required modifiers fields
   XSD: CheckinDate + CheckoutDate required in HotelStay
        NumberOfAdults required in HotelRateAndRuleModifiers
------------------------------------------------ */
if (!modifiers.checkin) {
  return res.status(400).json({
    success: false,
    message: "modifiers.checkin is required (HotelStay > CheckinDate)",
  });
}

if (!modifiers.checkout) {
  return res.status(400).json({
    success: false,
    message: "modifiers.checkout is required (HotelStay > CheckoutDate)",
  });
}

// numberOfAdults is OPTIONAL — defaults to 1 in service if not provided

    /* ------------------------------------------------
       LEVEL 4 — Validate HotelChain format
       XSD: typeHotelChainCode — exactly 2 characters
    ------------------------------------------------ */
    if (hotelProperty.hotelChain.length !== 2) {
      return res.status(400).json({
        success: false,
        message: "hotelProperty.hotelChain must be exactly 2 characters (e.g. 'LC', 'WI', 'HH')",
      });
    }

    /* ------------------------------------------------
       LEVEL 5 — Validate date format YYYY-MM-DD
       XSD: typeDate — xs:date without timezone
    ------------------------------------------------ */
    const dateRegex = /^\d{4}-\d{2}-\d{2}$/;

    if (!dateRegex.test(modifiers.checkin)) {
      return res.status(400).json({
        success: false,
        message: "modifiers.checkin must be in YYYY-MM-DD format (e.g. '2026-03-19')",
      });
    }

    if (!dateRegex.test(modifiers.checkout)) {
      return res.status(400).json({
        success: false,
        message: "modifiers.checkout must be in YYYY-MM-DD format (e.g. '2026-04-03')",
      });
    }

    /* ------------------------------------------------
       LEVEL 6 — Validate checkin is before checkout
    ------------------------------------------------ */
    if (new Date(modifiers.checkin) >= new Date(modifiers.checkout)) {
      return res.status(400).json({
        success: false,
        message: "modifiers.checkin must be before modifiers.checkout",
      });
    }

    /* ------------------------------------------------
       LEVEL 7 — Validate numberOfAdults
       XSD: NumberOfAdults type="xs:int" — must be positive integer
    ------------------------------------------------ */
    /*const adults = parseInt(modifiers.numberOfAdults, 10);
    if (isNaN(adults) || adults < 1) {
      return res.status(400).json({
        success: false,
        message: "modifiers.numberOfAdults must be a positive integer (minimum 1)",
      });
    }*/

      // REPLACE LEVEL 7 WITH THIS ↓
if (modifiers.numberOfAdults !== undefined) {
  const adults = parseInt(modifiers.numberOfAdults, 10);
  if (isNaN(adults) || adults < 1) {
    return res.status(400).json({
      success: false,
      message: "modifiers.numberOfAdults must be a positive integer (minimum 1)",
    });
  }
}

    /* ------------------------------------------------
       LEVEL 8 — Validate numberOfRooms if provided
       XSD: NumberOfRooms type="xs:int" default="1"
    ------------------------------------------------ */
    if (modifiers.numberOfRooms !== undefined) {
      const rooms = parseInt(modifiers.numberOfRooms, 10);
      if (isNaN(rooms) || rooms < 1) {
        return res.status(400).json({
          success: false,
          message: "modifiers.numberOfRooms must be a positive integer (minimum 1)",
        });
      }
    }

    /* ------------------------------------------------
       LEVEL 9 — Validate rateRuleDetail enum if provided
       XSD: typeRateRuleDetail — None | Complete | RatePlansOnly
    ------------------------------------------------ */
    const validRateRuleDetails = ["None", "Complete", "RatePlansOnly"];

    if (modifiers.rateRuleDetail && !validRateRuleDetails.includes(modifiers.rateRuleDetail)) {
      return res.status(400).json({
        success: false,
        message: `modifiers.rateRuleDetail must be one of: ${validRateRuleDetails.join(", ")}`,
      });
    }

    /* ------------------------------------------------
       LEVEL 10 — Validate currency format if provided
       XSD: typeCurrency — 3-character ISO code
    ------------------------------------------------ */
    if (modifiers.currency !== undefined) {
      if (typeof modifiers.currency !== "string" || modifiers.currency.length !== 3) {
        return res.status(400).json({
          success: false,
          message: "modifiers.currency must be a 3-character ISO currency code (e.g. 'INR', 'USD', 'EUR')",
        });
      }
    }

    /* ------------------------------------------------
       LEVEL 11 — Validate HotelLocation format if provided
       XSD: typeHotelLocationCode — minLength=3, maxLength=6
    ------------------------------------------------ */
    if (hotelProperty.hotelLocation !== undefined) {
      const locLen = hotelProperty.hotelLocation.length;
      if (locLen < 3 || locLen > 6) {
        return res.status(400).json({
          success: false,
          message: "hotelProperty.hotelLocation must be 3-6 characters (IATA code e.g. 'HYD', 'DEL')",
        });
      }
    }

    /* ------------------------------------------------
       LEVEL 12 — Validate Availability enum if provided
       XSD: typeHotelAvailability enumeration
    ------------------------------------------------ */
    const validAvailability = [
      "Available",
      "NotAvailable",
      "AvailableForOtherRates",
      "OnRequest",
      "Unknown",
    ];

    if (hotelProperty.availability && !validAvailability.includes(hotelProperty.availability)) {
      return res.status(400).json({
        success: false,
        message: `hotelProperty.availability must be one of: ${validAvailability.join(", ")}`,
      });
    }

    /* ------------------------------------------------
       LEVEL 13 — Validate ParticipationLevel if provided
       XSD: StringLength1 — "2" or "4" only
       "2" = Best Available Rate (1G, 1V)
       "4" = Lowest Possible Rate (1G, 1V, 1P)
    ------------------------------------------------ */
    if (hotelProperty.participationLevel !== undefined) {
      if (!["2", "4"].includes(String(hotelProperty.participationLevel))) {
        return res.status(400).json({
          success: false,
          message: "hotelProperty.participationLevel must be '2' (Best Available Rate) or '4' (Lowest Possible Rate)",
        });
      }
    }

    /* ------------------------------------------------
       LEVEL 14 — Validate address line lengths if provided
       XSD: typeUnstructuredAddress — each line max 50 chars
    ------------------------------------------------ */
    if (hotelProperty.address1 && hotelProperty.address1.length > 50) {
      return res.status(400).json({
        success: false,
        message: "hotelProperty.address1 must not exceed 50 characters",
      });
    }

    if (hotelProperty.address2 && hotelProperty.address2.length > 50) {
      return res.status(400).json({
        success: false,
        message: "hotelProperty.address2 must not exceed 50 characters",
      });
    }

    /* ------------------------------------------------
       LEVEL 15 — Validate distance object if provided
       XSD: common:Distance — Units, Value, Direction
    ------------------------------------------------ */
    if (hotelProperty.distance !== undefined) {
      const { distance } = hotelProperty;

      if (!distance.value) {
        return res.status(400).json({
          success: false,
          message: "hotelProperty.distance.value is required when distance is provided",
        });
      }

      if (!distance.direction) {
        return res.status(400).json({
          success: false,
          message: "hotelProperty.distance.direction is required when distance is provided",
        });
      }

      const validDirections = ["N", "S", "E", "W", "NE", "NW", "SE", "SW"];
      if (!validDirections.includes(distance.direction.toUpperCase())) {
        return res.status(400).json({
          success: false,
          message: `hotelProperty.distance.direction must be one of: ${validDirections.join(", ")}`,
        });
      }

      const validUnits = ["MI", "KM"];
      if (distance.units && !validUnits.includes(distance.units.toUpperCase())) {
        return res.status(400).json({
          success: false,
          message: "hotelProperty.distance.units must be 'MI' or 'KM'",
        });
      }
    }

    /* ------------------------------------------------
       LEVEL 16 — Validate hotelRating if provided
       XSD: HotelRating — RatingProvider required, Rating is xs:integer
    ------------------------------------------------ */
    if (hotelProperty.hotelRating !== undefined) {
      const { hotelRating } = hotelProperty;

      if (!hotelRating.provider) {
        return res.status(400).json({
          success: false,
          message: "hotelProperty.hotelRating.provider is required when hotelRating is provided (e.g. 'AAA', 'NTM')",
        });
      }

      if (hotelRating.rating !== undefined) {
        const rating = parseInt(hotelRating.rating, 10);
        if (isNaN(rating) || rating < 0 || rating > 5) {
          return res.status(400).json({
            success: false,
            message: "hotelProperty.hotelRating.rating must be an integer between 0 and 5",
          });
        }
      }
    }

    /* ------------------------------------------------
       LEVEL 17 — Validate rateKeys array if provided
       Each rateKey must have rateKey string and optional chainCode
    ------------------------------------------------ */
    if (modifiers.rateKeys !== undefined) {
      if (!Array.isArray(modifiers.rateKeys)) {
        return res.status(400).json({
          success: false,
          message: "modifiers.rateKeys must be an array e.g. [{ rateKey: '...', chainCode: 'LC' }]",
        });
      }

      for (let i = 0; i < modifiers.rateKeys.length; i++) {
        const rk = modifiers.rateKeys[i];

        if (!rk.rateKey) {
          return res.status(400).json({
            success: false,
            message: `modifiers.rateKeys[${i}].rateKey is required`,
          });
        }
      }
    }

    /* ------------------------------------------------
       LEVEL 18 — Validate children array if provided
       XSD: NumberOfChildren > Age type="xs:int" — age 1 to 17
    ------------------------------------------------ */
    if (modifiers.children !== undefined) {
      if (!Array.isArray(modifiers.children)) {
        return res.status(400).json({
          success: false,
          message: "modifiers.children must be an array e.g. [{ age: 5 }, { age: 10 }]",
        });
      }

      for (let i = 0; i < modifiers.children.length; i++) {
        const child = modifiers.children[i];

        if (child.age === undefined || child.age === null) {
          return res.status(400).json({
            success: false,
            message: `modifiers.children[${i}].age is required`,
          });
        }

        const age = parseInt(child.age, 10);
        if (isNaN(age) || age < 1 || age > 17) {
          return res.status(400).json({
            success: false,
            message: `modifiers.children[${i}].age must be between 1 and 17`,
          });
        }
      }
    }

    /* ------------------------------------------------
       LEVEL 19 — Validate beddingType if provided
       XSD: HotelBedding Type="typeBedding" — max 15 chars
    ------------------------------------------------ */
    const validBeddingTypes = ["King", "Queen", "Double", "Twin", "Single", "Full"];

    if (modifiers.beddingType !== undefined) {
      if (!validBeddingTypes.includes(modifiers.beddingType)) {
        return res.status(400).json({
          success: false,
          message: `modifiers.beddingType must be one of: ${validBeddingTypes.join(", ")}`,
        });
      }
    }

    /* ------------------------------------------------
       LEVEL 20 — Validate numberOfBeds if provided
       XSD: HotelBedding NumberOfBeds type="xs:int"
            Requires beddingType to be set
    ------------------------------------------------ */
    if (modifiers.numberOfBeds !== undefined) {
      if (!modifiers.beddingType) {
        return res.status(400).json({
          success: false,
          message: "modifiers.beddingType is required when modifiers.numberOfBeds is provided",
        });
      }

      const beds = parseInt(modifiers.numberOfBeds, 10);
      if (isNaN(beds) || beds < 0) {
        return res.status(400).json({
          success: false,
          message: "modifiers.numberOfBeds must be a non-negative integer",
        });
      }
    }

    /* ------------------------------------------------
       LEVEL 21 — Validate rateCategories if provided
       XSD: RateCategory type="typeOTACode" — max 8 per HotelDetailsModifiers
    ------------------------------------------------ */
    if (modifiers.rateCategories !== undefined) {
      if (Array.isArray(modifiers.rateCategories) && modifiers.rateCategories.length > 8) {
        return res.status(400).json({
          success: false,
          message: "modifiers.rateCategories allows a maximum of 8 rate categories",
        });
      }
    }

    /* ------------------------------------------------
       LEVEL 22 — Validate corporateDiscountIds if provided
       XSD: CorporateDiscountID — 1G/1V max 4, 1P max 1 + 30 negotiated
    ------------------------------------------------ */
    if (modifiers.corporateDiscountIds !== undefined) {
      const ids = modifiers.corporateDiscountIds;

      if (!Array.isArray(ids) && typeof ids !== "string") {
        return res.status(400).json({
          success: false,
          message: "modifiers.corporateDiscountIds must be a string or array of strings",
        });
      }

      if (Array.isArray(ids) && ids.length > 4) {
        return res.status(400).json({
          success: false,
          message: "modifiers.corporateDiscountIds allows maximum 4 IDs for 1G/1V providers",
        });
      }
    }

    /* ------------------------------------------------
       LEVEL 23 — Validate loyaltyCard if provided
       XSD: common:LoyaltyCard — SupplierCode + Number required
    ------------------------------------------------ */
    if (modifiers.loyaltyCard !== undefined) {
      const { loyaltyCard } = modifiers;

      if (!loyaltyCard.supplierCode) {
        return res.status(400).json({
          success: false,
          message: "modifiers.loyaltyCard.supplierCode is required when loyaltyCard is provided",
        });
      }

      if (!loyaltyCard.number) {
        return res.status(400).json({
          success: false,
          message: "modifiers.loyaltyCard.number is required when loyaltyCard is provided",
        });
      }
    }

    /* ------------------------------------------------
       LEVEL 24 — Validate returnMediaLinks and returnGuestReviews
       Must be boolean if provided
    ------------------------------------------------ */
    if (
      requestOptions?.returnMediaLinks !== undefined &&
      typeof requestOptions.returnMediaLinks !== "boolean"
    ) {
      return res.status(400).json({
        success: false,
        message: "requestOptions.returnMediaLinks must be true or false",
      });
    }

    if (
      requestOptions?.returnGuestReviews !== undefined &&
      typeof requestOptions.returnGuestReviews !== "boolean"
    ) {
      return res.status(400).json({
        success: false,
        message: "requestOptions.returnGuestReviews must be true or false",
      });
    }

    /* ------------------------------------------------
       FLATTEN PAYLOAD FOR SERVICE
       Maps nested controller structure to flat service input
    ------------------------------------------------ */
    const servicePayload = {

      // HotelProperty — required
      hotelChain:          hotelProperty.hotelChain,
      hotelCode:           hotelProperty.hotelCode,

      // HotelProperty — optional attributes
      hotelLocation:       hotelProperty.hotelLocation,
      hotelName:           hotelProperty.name,
      vendorLocationKey:   hotelProperty.vendorLocationKey,
      reserveRequirement:  hotelProperty.reserveRequirement,
      participationLevel:  hotelProperty.participationLevel,
      availability:        hotelProperty.availability,
      hotelTransportation: hotelProperty.hotelTransportation,

      // HotelProperty — optional child elements
      address1:            hotelProperty.address1,
      address2:            hotelProperty.address2,
      businessPhone:       hotelProperty.businessPhone,
      faxPhone:            hotelProperty.faxPhone,
      distance:            hotelProperty.distance,
      hotelRating:         hotelProperty.hotelRating,

      // Modifiers — required (map field names)
      checkinDate:         modifiers.checkin,    // "checkin"  → "checkinDate"
      checkoutDate:        modifiers.checkout,   // "checkout" → "checkoutDate"
      numberOfAdults:      modifiers.numberOfAdults,

      // Modifiers — optional
      numberOfRooms:       modifiers.numberOfRooms,
      rateRuleDetail:      modifiers.rateRuleDetail,
      currency:            modifiers.currency,
      rateKeys:            modifiers.rateKeys,
      loyaltyCard:         modifiers.loyaltyCard,
      corporateDiscountIds: modifiers.corporateDiscountIds,
      children:            modifiers.children,
      beddingType:         modifiers.beddingType,
      numberOfBeds:        modifiers.numberOfBeds,
      rateCategories:      modifiers.rateCategories,

      // RequestOptions — all optional
      returnMediaLinks:    requestOptions?.returnMediaLinks,
      returnGuestReviews:  requestOptions?.returnGuestReviews,
      policyReference:     requestOptions?.policyReference,
    };

    console.log("➡️ Service Payload:");
    console.log(JSON.stringify(servicePayload, null, 2));

    /* ------------------------------------------------
       CALL SERVICE
    ------------------------------------------------ */
    const result = await fetchHotelRateAndRule(servicePayload);

    console.log("✅ CONTROLLER: HotelRateAndRuleReq - SUCCESS");

    return res.status(200).json({
      success: true,
      message: "Hotel rate and rule fetched successfully",
      data: result,
    });

  } catch (error) {
    console.error("❌ CONTROLLER ERROR: HotelRateAndRuleReq");
    console.error(error.message);

    return res.status(500).json({
      success: false,
      message: "Hotel rate and rule request failed",
      error: error.message,
    });

  } finally {
    console.log("CONTROLLER: HotelRateAndRuleReq - END");
    console.log("==================================================");
  }
};
  
  
  