"use strict";
/**
 * Handles PNR divide for ALL passenger combinations:
 *
 * SINGLE PASSENGER:
 *   { "BookingTravelerRefKey": "KEY1" }
 *
 * ADT + INF PAIR (must always be together):
 *   { "BookingTravelerRefKey": ["ADT_KEY", "INF_KEY"] }
 *
 * MULTIPLE PASSENGERS INTO ONE CHILD UR:
 *   { "BookingTravelerRefKey": ["ADT_KEY1", "INF_KEY1", "CNN_KEY"] }
 *
 * MULTIPLE PASSENGERS EACH INTO SEPARATE CHILD URs:
 *   → Call this API multiple times, one call per passenger/pair
 *   → Each call creates its own child UR + PnrSplitHistory row
 *
 * INF RULE (Travelport enforced):
 *   INF MUST always be divided with its accompanying ADT.
 *   Never divide INF alone. Never divide ADT alone when INF is linked.
 *
 * travelerTypes (optional field):
 *   Helps validate INF+ADT rule before hitting Travelport.
 *   Format: { "KEY1": "ADT", "KEY2": "INF", "KEY3": "CNN" }
 */

const travelportService = require("../services/pnrDivide.service.js");
const db = require('../../../busapi/configs/dbConnection');

// =============================================================================
// Validate passenger key combinations BEFORE calling Travelport
//
// Catches invalid combinations early (saves Travelport round-trip):
//   ❌ INF alone          → rejected
//   ❌ ADT alone + INF    → rejected (if travelerTypes provided)
//   ✅ ADT + INF together → allowed
//   ✅ CNN alone          → allowed
//   ✅ 2ADT + 2INF        → allowed (all together in one call)
// =============================================================================
const validateTravelerKeys = (keys, travelerTypes = {}) => {
  const TAG = "[validateTravelerKeys]";

  if (!keys || keys.length === 0) {
    return { valid: false, reason: "At least one BookingTravelerRefKey is required" };
  }

  if (Object.keys(travelerTypes).length > 0) {
    const typesInRequest = keys.map((k) => travelerTypes[k]).filter(Boolean);
    const hasINF = typesInRequest.includes("INF");
    const hasADT = typesInRequest.includes("ADT");

    console.log(`${TAG} Types in request: ${typesInRequest.join(", ")}`);

    // INF without ADT is always rejected
    if (hasINF && !hasADT) {
      return {
        valid: false,
        reason: "INF (infant) cannot be divided without its accompanying ADT. Add the ADT key.",
        infRule: "INF must always travel with and be divided with its accompanying ADT",
      };
    }
  }

  return { valid: true };
};

exports.resDividereq = async (req, res) => {
  const TAG = "[reservationDivide.controller]";

  try {
    const {
      UniversalRecordLocatorCode,
      ProviderLocatorCode,
      BookingTravelerRefKey,
      travelerTypes = {},
    } = req.body;

    // ── Basic validation ──────────────────────────────────────────────────────
    if (!UniversalRecordLocatorCode || !ProviderLocatorCode || !BookingTravelerRefKey) {
      return res.status(400).json({
        success: false,
        message: "Missing required fields: UniversalRecordLocatorCode, ProviderLocatorCode, BookingTravelerRefKey",
        examples: {
          singlePassenger:  { BookingTravelerRefKey: "KEY1" },
          adtWithInfant:    { BookingTravelerRefKey: ["ADT_KEY", "INF_KEY"] },
          multipleInOneUR:  { BookingTravelerRefKey: ["KEY1", "KEY2", "KEY3"] },
        },
      });
    }

    // Normalise to array
    const travelerKeys = Array.isArray(BookingTravelerRefKey)
      ? BookingTravelerRefKey
      : [BookingTravelerRefKey];

    // Validate combinations
    const validation = validateTravelerKeys(travelerKeys, travelerTypes);
    if (!validation.valid) {
      return res.status(400).json({
        success: false,
        message: validation.reason,
        infRule: validation.infRule,
      });
    }

    console.log(`${TAG} ─────────────────────────────────────────────────────`);
    console.log(`${TAG} UniversalRecordLocatorCode : ${UniversalRecordLocatorCode}`);
    console.log(`${TAG} ProviderLocatorCode        : ${ProviderLocatorCode}`);
    console.log(`${TAG} Traveler count             : ${travelerKeys.length}`);
    travelerKeys.forEach((k, i) => {
      console.log(`${TAG}   [${i}] ${k} (${travelerTypes[k] || "type unknown"})`);
    });
    console.log(`${TAG} ─────────────────────────────────────────────────────`);

    // =========================================================================
    // STEP 1: Auto-fetch booking_id from uflights
    // =========================================================================
    let bookingId = null;
    try {
      console.log(`${TAG} STEP 1: Fetching booking_id WHERE UniversalLocator=${UniversalRecordLocatorCode}`);

      const [ufRows] = await db.query(
        `SELECT booking_id, UniversalLocator, Status
         FROM uflights WHERE UniversalLocator = ? LIMIT 1`,
        [UniversalRecordLocatorCode]
      );

      if (ufRows && ufRows.length > 0) {
        bookingId = ufRows[0].booking_id;
        console.log(`${TAG} ✅ STEP 1: booking_id=${bookingId}`);
      } else {
        console.warn(`${TAG} ⚠️  STEP 1: No uflights row found. booking_id=null`);
      }
    } catch (dbErr) {
      console.error(`${TAG} ❌ STEP 1 error: ${dbErr.message}`);
    }

    // =========================================================================
    // STEP 2: Call Travelport divide
    // All traveler keys passed → all go into ONE child UR
    // =========================================================================
    console.log(`${TAG} STEP 2: Calling Travelport divide...`);

    const response = await travelportService.resDividereq(
      UniversalRecordLocatorCode,
      ProviderLocatorCode,
      travelerKeys
    );

    console.log(`${TAG} ✅ STEP 2: Divide successful. TraceId=${response.traceId}`);

    const { childLocators } = response;
    console.log(`${TAG}   childLocators: ${JSON.stringify(childLocators)}`);

    // =========================================================================
    // STEP 3: Insert into PnrSplitHistory
    //
    // One row per divide call — passenger_keys stores ALL keys in this call.
    //
    // SCENARIO A (each pax own UR):  3 divide calls → 3 PnrSplitHistory rows
    //   row 1: passenger_keys=["ADT_KEY","INF_KEY"]
    //   row 2: passenger_keys=["ADT_KEY2","INF_KEY2"]
    //   row 3: passenger_keys=["CNN_KEY"]
    //
    // SCENARIO B (all pax one UR):   1 divide call → 1 PnrSplitHistory row
    //   row 1: passenger_keys=["ADT_KEY","INF_KEY","CNN_KEY"]
    // =========================================================================
    let splitHistoryId = null;
    try {
      console.log(`${TAG} STEP 3: Inserting into PnrSplitHistory...`);

      const passengerKeysJson = JSON.stringify(travelerKeys);

      console.log(`${TAG}   booking_id     : ${bookingId}`);
      console.log(`${TAG}   parent_locator : ${UniversalRecordLocatorCode}`);
      console.log(`${TAG}   child_locator  : ${childLocators?.childUniversalLocator}`);
      console.log(`${TAG}   gds_locator    : ${childLocators?.childGdsLocator}`);
      console.log(`${TAG}   passenger_keys : ${passengerKeysJson}`);

      const [insertResult] = await db.query(
        `INSERT INTO PnrSplitHistory
           (booking_id, parent_locator, child_locator, gds_locator, passenger_keys, status)
         VALUES (?, ?, ?, ?, ?, 'Active')`,
        [
          bookingId,
          UniversalRecordLocatorCode,
          childLocators?.childUniversalLocator || null,
          childLocators?.childGdsLocator       || null,
          passengerKeysJson,
        ]
      );

      splitHistoryId = insertResult.insertId;
      console.log(`${TAG} ✅ STEP 3: PnrSplitHistory id=${splitHistoryId}`);

    } catch (dbErr) {
      console.error(`${TAG} ❌ STEP 3 INSERT failed: ${dbErr.message} | Code: ${dbErr.code}`);
    }

    return res.status(200).json({
      success: true,
      message: `PNR divided. ${travelerKeys.length} passenger(s) moved to child PNR.`,
      traceId:          response.traceId,
      splitHistoryId,
      bookingId,
      passengersDivided: travelerKeys.length,
      childLocators: {
        child_locator: childLocators?.childUniversalLocator || null,
        gds_locator:   childLocators?.childGdsLocator       || null,
      },
      travelportResponse: response.json,
    });

  } catch (error) {
    console.error(`${TAG} Error: ${error.message}`);
    return res.status(500).json({ success: false, message: error.message });
  }
};