require("dotenv").config();
const axios = require("axios");
const path = require("path");
const fs = require("fs");
const { getAccessToken } = require("./authToken.js");

const generateTraceId = () => {
  return `BOBROS-${Date.now()}`;
  //return "trace-stay-001"
};

// Reuse the trace id the front-end sent back (so the whole
// stayService -> createReservation flow shares ONE id); otherwise mint a new
// BOBROS-<timestamp>. Used only by the chained calls.
const resolveTraceId = (incoming) =>
  typeof incoming === "string" && incoming.trim()
    ? incoming.trim()
    : generateTraceId();

const saveDebugJson = (fileName, jsonData) => {
  try {
    const debugDir = path.resolve(__dirname, "../debug-json");
    if (!fs.existsSync(debugDir)) fs.mkdirSync(debugDir, { recursive: true });
    const data =
      typeof jsonData === "string" ? jsonData : JSON.stringify(jsonData, null, 2);
    fs.writeFileSync(path.join(debugDir, fileName), data);
  } catch (err) {
    console.error(`Debug save error: ${err.message}`);
  }
};

// ── STEP 1 of the chain: SEARCH ──────────────────────────────────────────────
// traceId is optional. On the first call leave it empty -> a new BOBROS id is
// generated. Returns { data, traceId } so the controller can send traceId back
// to the front-end.
exports.callStayService = async (payload, endPoint, traceId) => {
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
  const url = `${process.env.BASEURLV12}${endPoint}`;
  const trace = resolveTraceId(traceId);
  try {
    //console.log(JSON.stringify(payload, null, 2));
    const token = await getAccessToken();
    console.log("tokenreceived: ", token);
    console.log("4. Sending to Travelport...");
    const headers = {
      "Content-Type": "application/json",
      "Accept": "application/json",
      "tvp-trace-id":trace,
      "Authorization": `Bearer ${token}`,
      "XAUTH_TRAVELPORT_ACCESSGROUP": process.env.ACCESS_GROUP,
    
    };

    console.log("headers: ", headers);
    console.log("traceId: ", trace);
    console.log(url);

    // log the REQUEST before sending (now includes the headers + traceId)
    saveDebugJson(`stayRequest_${ts}_request.json`, {
      url,
      method: "POST",
      traceId: trace,
      headers,
      body: payload,
    });

    const response = await axios.post(url, payload, { headers });
    console.log("5. Response received:", response.status);
    console.log(response.data);

    // log the RESPONSE after receiving (carry the same traceId)
    saveDebugJson(`stayResponse_${ts}_response.json`, {
      status: response.status,
      traceId: trace,
      headers: response.headers,
      data: response.data,
    });

    return { data: response.data };
  } catch (error) {
    saveDebugJson(`stay_${ts}_error.json`, {
      traceId: trace,
      status: error.response?.status || "NO_RESPONSE",
      data: error.response?.data || { message: error.message },
    });
    console.error("API Call failed", error.response?.data || error.message);
    throw error;
  }
};

// ── PAGINATION (NOT chained) ─────────────────────────────────────────────────
// Self-generates its own trace id. Returns response.data unchanged.
exports.callPaginationService = async (pageNo, paginationCode) => {
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
  const url = `${process.env.BASEURLV12}/search/searchcomplete/${paginationCode}?pageNumber=${pageNo}`;
  const trace = generateTraceId();
  try {
    console.log(process.env.BASEURLV12);
    console.log(pageNo, paginationCode);
    const token = await getAccessToken();
    console.log("4. Sending to Travelport...");

    // build headers as a const so we can log exactly what we send
    const headers = {
      "Content-Type": "Application/json",
      "Accept": "Application/json",
      "Authorization": `Bearer ${token}`,
      "XAUTH_TRAVELPORT_ACCESSGROUP": process.env.ACCESS_GROUP,
      
    };

    console.log("headers: ", headers);

    // log the REQUEST before sending (now includes the headers + traceId)
    saveDebugJson(`paginationRequest_${ts}_request.json`, {
      url,
      method: "GET",
      traceId: trace,
      pageNo,
      paginationCode,
      headers,
    });

    const response = await axios.get(url, { headers, timeout: 30000 });
    console.log("5. Response received:", response.status);
    console.log(response.data);

    // log the RESPONSE after receiving
    saveDebugJson(`paginationResponse_${ts}_response.json`, {
      status: response.status,
      traceId: trace,
      headers: response.headers,
      data: response.data,
    });

    return response.data;
  } catch (error) {
    saveDebugJson(`pagination_${ts}_error.json`, {
      traceId: trace,
      status: error.response?.status || "NO_RESPONSE",
      data: error.response?.data || { message: error.message },
    });
    console.error("Availability API failed", error.response?.data || error.message);
    throw error;
  }
};

// ── LAST STEP of the chain: CREATE RESERVATION ───────────────────────────────
// traceId comes from the front-end (the same BOBROS id it received from search).
// Returns { data, traceId }.
exports.callReservationService = async (payload, endPoint, traceId) => {
  const ts = new Date().toISOString().replace(/[:.]/g, "-");

  // append the accept-change flags so a price/guarantee change comes back as a
  // warning and the booking still completes (instead of erroring 13020)
  const baseUrl = `${process.env.BASEURLV11}${endPoint}`;
  const url = baseUrl.includes("?")
    ? `${baseUrl}&acceptPriceChangeInd=true&acceptGuaranteeChangeInd=true`
    : `${baseUrl}?acceptPriceChangeInd=true&acceptGuaranteeChangeInd=true`;

  const trace = resolveTraceId(traceId);

  try {
    console.log(url);
    console.log(JSON.stringify(payload, null, 2));
    const token = await getAccessToken();
    // console.log ("tokenreceived: ", token)
    console.log("4. Sending to Travelport...");
    const headers = {
      "Content-Type": "application/json",
      "Accept": "application/json",
      "tvp-trace-id":trace,
      "Authorization": `Bearer ${token}`,
      "XAUTH_TRAVELPORT_ACCESSGROUP": process.env.ACCESS_GROUP,

    };
    console.log("headers: ", headers);
    console.log("traceId: ", trace);
    console.log(payload);

    // log the REQUEST before sending
    saveDebugJson(`reservationRequest_${ts}_request.json`, {
      url,
      method: "POST",
      traceId: trace,
      headers,
      body: payload,
    });

    const response = await axios.post(url, payload, { headers });
    console.log("5. Response received:", response.status);
    console.log(response.data);

    // log the RESPONSE after receiving
    saveDebugJson(`reservationResponse_${ts}_response.json`, {
      status: response.status,
      traceId: trace,
      headers: response.headers,
      data: response.data,
    });

    return { data: response.data, traceId: trace };
  } catch (error) {
    saveDebugJson(`reservation_${ts}_error.json`, {
      traceId: trace,
      status: error.response?.status || "NO_RESPONSE",
      data: error.response?.data || { message: error.message },
    });
    console.error("API Call failed", error.response?.data || error.message);
    console.log(error);
    throw error;
  }
};

// ── RESERVATION STATUS (NOT chained) ─────────────────────────────────────────
exports.reservationStatus = async (id, endPoint, traceId) => {
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
  const url = `${process.env.BASEURLV11}/${endPoint}/${id}`;
  const trace = resolveTraceId(traceId);   // now traceId is defined (it's a param)
  try {
    console.log("reservation status check req received");
    const token = await getAccessToken();
    console.log("4. Sending to Travelport...");
    const headers = {
      "Content-Type": "Application/json",
      "Accept": "Application/json",
      "tvp-trace-id":traceId,
      "Authorization": `Bearer ${token}`,
      "XAUTH_TRAVELPORT_ACCESSGROUP": process.env.ACCESS_GROUP,
     
    };

    saveDebugJson(`reservationStatusRequest_${ts}_request.json`, {
      url,
      method: "GET",
      id,
      endPoint,
      headers,
    });

    const response = await axios.get(url, { headers, timeout: 30000 });
    console.log("5. Response received:", response.status);
    console.log(response.data);

    saveDebugJson(`reservationStatusResponse_${ts}_response.json`, {
      status: response.status,
      traceId: trace,
      headers: response.headers,
      data: response.data,
    });

    return response.data;
  } catch (error) {
    saveDebugJson(`reservationStatus_${ts}_error.json`, {
      traceId: trace,
      status: error.response?.status || "NO_RESPONSE",
      data: error.response?.data || { message: error.message },
    });
    console.error("Availability API failed", error.response?.data || error.message);
    throw error;
  }
};

// ── CANCEL (NOT chained) ─────────────────────────────────────────────────────
exports.cancelReservation = async (endPoint) => {
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
  const url = `${process.env.BASEURLV11}/${endPoint}`;
  const trace = generateTraceId();
  try {
    console.log("reservation cancel req received");

    const token = await getAccessToken(); // FIX: was commented out, so `token` was undefined
    console.log("4. Sending to Travelport...");
    console.log(url);

    const headers = {
      "Content-Type": "application/json",
      "Accept": "application/json",
      "Authorization": `Bearer ${token}`,
      "XAUTH_TRAVELPORT_ACCESSGROUP": process.env.ACCESS_GROUP,
      
    };

    console.log("headers: ", headers);

    // log the REQUEST before sending (cancel has no body)
    saveDebugJson(`cancelRequest_${ts}_request.json`, {
      url,
      method: "PUT",
      traceId: trace,
      headers,
      body: null,
    });

    const response = await axios.put(
      url,
      null, // FIX: cancel sends no body
      { headers } // FIX: headers must go in the config, not as the body
    );
    console.log("5. Response received:", response.status);
    console.log(response.data);

    // log the RESPONSE after receiving
    saveDebugJson(`cancelRequest_${ts}_response.json`, {
      status: response.status,
      traceId: trace,
      headers: response.headers,
      data: response.data,
    });

    return response.data;
  } catch (error) {
    saveDebugJson(`cancel_${ts}_error.json`, {
      traceId: trace,
      status: error.response?.status || "NO_RESPONSE",
      data: error.response?.data || { message: error.message },
    });
    console.error("Availability API failed", error.response?.data || error.message);
    throw error;
  }
};