const seatMapService = require("../services/seatmapService");

// Passenger codes that don't get a seat (kept in sync with the service).
const NON_SEATED_PAX = new Set(["INF", "INS", "LAP"]);
const SUPPORTED_PROVIDERS = new Set(["ACH", "1G"]);

// ============================================================
// CONTROLLER
// ============================================================

exports.getSeatMap = async (req, res) => {
  try {
    const body = req.body || {};
    const type = body.type || "preBooking";

    // Post-booking is handled in a separate flow — not enabled on this endpoint yet.
    if (type === "postBooking") {
      return res.status(501).json({
        success: false,
        message: "Post-booking seat map is handled separately and is not enabled on this endpoint yet",
      });
    }

    // ---- pre-booking validation ----
    const errors = validatePreBooking(body);
    if (errors.length) {
      return res.status(400).json({
        success: false,
        message: "Validation failed",
        errors,
      });
    }

    const result = await seatMapService.getSeatMap(body);
    return res.json({
      success: true,
      data: result, // raw Travelport response per segment (normalization TBD)
    });
  } catch (error) {
    console.error("SeatMap Controller Error:", error.message);
    return res.status(500).json({
      success: false,
      message: error.message,
    });
  }
};

// ============================================================
// VALIDATION (pre-booking)
// ============================================================
//
// Collects ALL problems and returns them together, so the caller fixes
// everything in one pass instead of one error at a time.
//
function validatePreBooking(body) {
  const errors = [];

  // ---- provider ----
  const provider = String(body.providerCode || "").toUpperCase();
  if (!body.providerCode) {
    errors.push("providerCode is required (ACH or 1G)");
  } else if (!SUPPORTED_PROVIDERS.has(provider)) {
    errors.push(`Unsupported providerCode "${body.providerCode}" (expected ACH or 1G)`);
  }

  // ---- segments ----
  const segments = body.segments;
  if (!Array.isArray(segments) || segments.length === 0) {
    errors.push("segments[] is required and must be non-empty");
  } else {
    segments.forEach((seg, i) => {
      const at = `segments[${i}]`;
      if (!seg || typeof seg !== "object") {
        errors.push(`${at} must be an object`);
        return;
      }
      if (!seg.key) errors.push(`${at}.key is required`);

      // provider-specific required field (the one thing the raw segment lacks)
      if (provider === "ACH") {
        const token = seg.hostToken || body.hostToken;
        if (!token || !token.value) {
          errors.push(`${at}.hostToken.value is required for ACH (verbatim token body from itinerary HostToken)`);
        }
      } else if (provider === "1G") {
        if (!seg.cabinClass) {
          errors.push(`${at}.cabinClass is required for 1G (from BookingInfo.CabinClass)`);
        }
      }
    });
  }

  // ---- travelers ----
  const travelers = body.travelers;
  if (!Array.isArray(travelers) || travelers.length === 0) {
    errors.push("travelers[] is required and must be non-empty");
  } else {
    const seated = travelers.filter(
      (t) => !NON_SEATED_PAX.has(String(t.type || t.code || "ADT").toUpperCase())
    );
    if (seated.length === 0) {
      errors.push("travelers[] must include at least one seat-eligible (non-infant) passenger");
    }
    // Validate only seated travelers — infants are dropped from the seat map.
    travelers.forEach((t, i) => {
      const code = String(t.type || t.code || "ADT").toUpperCase();
      if (NON_SEATED_PAX.has(code)) return;
      const at = `travelers[${i}]`;
      if (!t.key) errors.push(`${at}.key is required`);
      if (!t.firstName) errors.push(`${at}.firstName is required`);
      if (!t.lastName) errors.push(`${at}.lastName is required`);
    });
  }

  return errors;
}