// // src/controllers/flightController.js
// const axios = require('axios');
// const travelportConfig = require('../config/travelport_lowfaresearch');
// const { getBearerToken, invalidateToken, getTokenStatus } = require('../services/authService');
// const { buildLowFareSearchPayload } = require('../utils/requestBuilder');
// const { transformLowFareResponse } = require('../utils/responseTransformer');
// const { saveDebugJson, getTimestamp } = require('../utils/Debuglogger');

// /**
//  * POST /flights/low-fare-search
//  *
//  * Bearer token is fetched automatically via OAuth and cached for 24 hours.
//  * If a 401 is received mid-session, the token is invalidated and retried once.
//  * Raw request and response are saved to /logs folder (same pattern as XML logger).
//  */
// async function lowFareSearch(req, res, next) {
//   try {
//     const { rawResponse = false, ...searchInput } = req.body;

//     // 1. Build Travelport request payload from simplified input
//     const travelportPayload = buildLowFareSearchPayload(searchInput);

//     // 2. Get Bearer token (served from cache or fetched via OAuth automatically)
//     let bearerToken = await getBearerToken();
//     let headers = travelportConfig.buildHeaders(bearerToken);

//     const traceId =
//   travelportPayload?.CatalogProductOfferingsQueryRequest
//     ?.CatalogProductOfferingsRequest
//     ?.traceId;
//     const timestamp = getTimestamp();
//     const url = `${travelportConfig.baseUrl}${travelportConfig.endpoints.lowFareSearch}`;

//     // 3. Save raw request to logs (same as: saveDebugXml(`AirCreateReq-${traceId}-${timestamp}.xml`, xml))
//     saveDebugJson(`LowFareReq-${traceId}-${timestamp}.json`, travelportPayload);
//     console.log(`[${traceId}] Request JSON saved to logs folder`);

//     let travelportResponse;
//     try {
//       // 4. Call Travelport
//       console.log(`[LowFareSearch] POST ${url}  TraceId: ${traceId}`);
//       travelportResponse = await axios.post(url, travelportPayload, {
//         headers,
//         timeout: 30000,
//       });
//     } catch (axiosErr) {
//       // 5. If 401 — token may have expired early; invalidate and retry once
//       if (axiosErr.response?.status === 401) {
//         console.warn('[LowFareSearch] 401 received — invalidating token and retrying...');
//         invalidateToken();
//         bearerToken = await getBearerToken();
//         headers = travelportConfig.buildHeaders(bearerToken);
//         travelportResponse = await axios.post(url, travelportPayload, {
//           headers,
//           timeout: 30000,
//         });
//       } else {
//         // Save error response to logs before throwing
//         if (axiosErr.response?.data) {
//           saveDebugJson(`LowFareRsp-${traceId}-${timestamp}-ERROR.json`, axiosErr.response.data);
//           console.log(`[${traceId}] Error response saved to logs folder`);
//         }
//         throw axiosErr;
//       }
//     }

//     // 6. Save raw response to logs (same as: saveDebugXml(`AirCreateRsp-${traceId}-${timestamp}.xml`, response.data))
//     saveDebugJson(`LowFareRsp-${traceId}-${timestamp}.json`, travelportResponse.data);
//     console.log(`[${traceId}] Response JSON saved to logs folder`);

//     // 7. Transform into clean structure
//     const transformed = transformLowFareResponse(travelportResponse.data);

//     // const responsePayload = { ...transformed };
//     // if (rawResponse) {
//     //   responsePayload.rawTravelportResponse = travelportResponse.data;
//     // }

//     // return res.status(200).json(responsePayload);
//     const responsePayload = {
//   traceId,
//   ...transformed,
// };

// if (rawResponse) {
//   responsePayload.rawTravelportResponse = travelportResponse.data;
// }

// return res.status(200).json(responsePayload);
//   } catch (err) {
//     next(err);
//   }
// }

// /**
//  * GET /flights/health
//  * Shows server status, OAuth config status, and token cache info.
//  */
// function healthCheck(req, res) {
//   const requiredEnvVars = [
//     'TRAVELPORT_USERNAME_JSON',
//     'TRAVELPORT_PASSWORD_JSON',
//     'TRAVELPORT_CLIENT_ID',
//     'TRAVELPORT_CLIENT_SECRET',
//     'TRAVELPORT_ACCESS_GROUP',
//     'TRAVELPORT_PCC_CORE',
//   ];

//   const missing = requiredEnvVars.filter((v) => !process.env[v]);
//   const configOk = missing.length === 0;
//   const tokenStatus = getTokenStatus();

//   return res.status(200).json({
//     status:      'ok',
//     service:     'Travelport Flight API',
//     environment: process.env.TRAVELPORT_ENV || 'preProduction',
//     baseUrl:     travelportConfig.baseUrl,
//     config: {
//       ready:       configOk,
//       missingVars: missing.length ? missing : undefined,
//       message:     configOk
//         ? 'All credentials are configured.'
//         : `Missing .env variables: ${missing.join(', ')}`,
//     },
//     tokenCache: tokenStatus,
//     timestamp: new Date().toISOString(),
//   });
// }

// module.exports = { lowFareSearch, healthCheck };





// src/controllers/flightController.js
const axios = require('axios');
const travelportConfig = require('../config/travelport_lowfaresearch');
const { getBearerToken, invalidateToken, getTokenStatus } = require('../services/authService');
const { buildLowFareSearchPayload } = require('../utils/requestBuilder');
const { transformLowFareResponse } = require('../utils/responseTransformer');
const { saveDebugJson, getTimestamp } = require('../utils/Debuglogger');

/**
 * POST /flights/low-fare-search
 *
 * Bearer token is fetched automatically via OAuth and cached for 24 hours.
 * If a 401 is received mid-session, the token is invalidated and retried once.
 * Raw request and response are saved to /logs folder.
 *
 * RESPONSE includes sessionKeys: { traceId, travelerRefs }
 * The client MUST store these and send them in the Pricing request so
 * the same TraceId and BookingTravelerRef keys are reused across the
 * full Search → Pricing → Reservation → Ticketing flow (Travelport checklist).
 */
async function lowFareSearch(req, res, next) {
  try {
    const { rawResponse = false, ...searchInput } = req.body;

    // 1. Build Travelport request payload + capture session keys
    //    buildLowFareSearchPayload now returns { payload, sessionKeys }
    const { payload: travelportPayload, sessionKeys } =
      buildLowFareSearchPayload(searchInput);

    // sessionKeys = { traceId, travelerRefs: { ADT: '...', INF: '...', CNN: '...' } }
    const { traceId, travelerRefs } = sessionKeys;

    // 2. Get Bearer token (served from cache or fetched via OAuth)
    let bearerToken = await getBearerToken();
    let headers = travelportConfig.buildHeaders(bearerToken);

    const timestamp = getTimestamp();
    const url = `${travelportConfig.baseUrl}${travelportConfig.endpoints.lowFareSearch}`;

    // 3. Save raw request to logs
    saveDebugJson(`LowFareReq-${traceId}-${timestamp}.json`, travelportPayload);
    console.log(`[${traceId}] Request JSON saved to logs folder`);

    let travelportResponse;
    try {
      // 4. Call Travelport
      console.log(`[LowFareSearch] POST ${url}  TraceId: ${traceId}`);
      travelportResponse = await axios.post(url, travelportPayload, {
        headers,
        timeout: 30000,
      });
    } catch (axiosErr) {
      // 5. If 401 — token may have expired early; invalidate and retry once
      if (axiosErr.response?.status === 401) {
        console.warn('[LowFareSearch] 401 received — invalidating token and retrying...');
        invalidateToken();
        bearerToken = await getBearerToken();
        headers = travelportConfig.buildHeaders(bearerToken);
        travelportResponse = await axios.post(url, travelportPayload, {
          headers,
          timeout: 30000,
        });
      } else {
        if (axiosErr.response?.data) {
          saveDebugJson(
            `LowFareRsp-${traceId}-${timestamp}-ERROR.json`,
            axiosErr.response.data
          );
          console.log(`[${traceId}] Error response saved to logs folder`);
        }
        throw axiosErr;
      }
    }

    // 6. Save raw response to logs
    saveDebugJson(`LowFareRsp-${traceId}-${timestamp}.json`, travelportResponse.data);
    console.log(`[${traceId}] Response JSON saved to logs folder`);

    // 7. Transform into clean structure
    const transformed = transformLowFareResponse(travelportResponse.data);

    // 8. Build final response
    //    sessionKeys are included so the client can pass them directly
    //    into the Pricing request without having to re-generate or guess.
    //
    //    Expected client usage:
    //      const { sessionKeys, flights } = await lowFareSearch(input);
    //      const pricing = await airPrice({ ...selection, sessionKeys });
    const responsePayload = {
      // ✅ Checklist: traceId returned so client reuses it in Pricing + Reservation
      

      // ✅ Checklist: travelerRefs returned so client reuses the exact same
      // BookingTravelerRef keys in Pricing and AirCreateReservation
      // Shape: { ADT: 'base64key==', INF: 'base64key==', CNN: 'base64key==' }
      travelerRefs,

      // Transformed flight results
      ...transformed,
    };

    if (rawResponse) {
      responsePayload.rawTravelportResponse = travelportResponse.data;
    }

    return res.status(200).json(responsePayload);

  } catch (err) {
    next(err);
  }
}

/**
 * GET /flights/health
 */
function healthCheck(req, res) {
  const requiredEnvVars = [
    'TRAVELPORT_USERNAME_JSON',
    'TRAVELPORT_PASSWORD_JSON',
    'TRAVELPORT_CLIENT_ID',
    'TRAVELPORT_CLIENT_SECRET',
    'TRAVELPORT_ACCESS_GROUP',
    'TRAVELPORT_PCC_CORE',
  ];

  const missing = requiredEnvVars.filter((v) => !process.env[v]);
  const configOk = missing.length === 0;
  const tokenStatus = getTokenStatus();

  return res.status(200).json({
    status:      'ok',
    service:     'Travelport Flight API',
    environment: process.env.TRAVELPORT_ENV || 'preProduction',
    baseUrl:     travelportConfig.baseUrl,
    config: {
      ready:       configOk,
      missingVars: missing.length ? missing : undefined,
      message:     configOk
        ? 'All credentials are configured.'
        : `Missing .env variables: ${missing.join(', ')}`,
    },
    tokenCache: tokenStatus,
    timestamp: new Date().toISOString(),
  });
}

module.exports = { lowFareSearch, healthCheck };