"use strict";
const { createPNR } = require("../services/airCreateReservationUpdatedSevice.js");

const VALID_PTC_CODES = ["ADT", "CHD", "CNN", "INF"];
const PTC_MAPPING = {
  "ADT": "ADT",
  "CNN": "CHD", 
  "CNN": "CNN",  // Map CNN to CHD for XML
  "INF": "INF"
};

exports.createBooking = async (req, res) => {
  const startTime = Date.now();
  const traceId = req.body.traceId || `BOOK-${Date.now()}`;

  console.log(`\n[${traceId}] 🟢 NEW BOOKING REQUEST`);
  console.log(`[${traceId}] Request body keys:`, Object.keys(req.body));

  try {
    // 1. Validate traceId
    if (!req.body.traceId) {
      return res.status(400).json({
        success: false,
        message: "traceId is required."
      });
    }

    // 2. Validate pricingResponse
    if (!req.body.pricingResponse) {
      return res.status(400).json({
        success: false,
        traceId,
        message: "pricingResponse is required."
      });
    }

    // 3. Validate passengerKeys (CRITICAL!)
    if (!req.body.passengerKeys || !Array.isArray(req.body.passengerKeys) || req.body.passengerKeys.length === 0) {
      return res.status(400).json({
        success: false,
        traceId,
        message: "passengerKeys array is required from pricing response."
      });
    }

    // 4. Validate selectedFareIndex (optional, default 0)
    const selectedFareIndex = req.body.selectedFareIndex !== undefined ? req.body.selectedFareIndex : 0;

    // 5. Validate passengers
    const passengers = req.body.passengers;
    if (!Array.isArray(passengers) || passengers.length === 0) {
      return res.status(400).json({
        success: false,
        traceId,
        message: "passengers array is required and must not be empty."
      });
    }

    // ========== EXTRACT AND VALIDATE CONTACT INFO ==========
    const contactInfo = req.body.contactInfo || {};
    
    // Validate email format if provided
    if (contactInfo.email && !isValidEmail(contactInfo.email)) {
      return res.status(400).json({
        success: false,
        traceId,
        message: "Invalid email format in contactInfo.email"
      });
    }
    
    // Validate phone if provided
    if (contactInfo.phone) {
      if (!contactInfo.phone.number) {
        return res.status(400).json({
          success: false,
          traceId,
          message: "contactInfo.phone.number is required when phone is provided"
        });
      }
      // Optional: Validate phone number format
      if (!isValidPhone(contactInfo.phone.number)) {
        console.log(`[${traceId}] ⚠️ Phone number may be invalid: ${contactInfo.phone.number}`);
      }
    }
    
    // Validate address if provided (for first passenger)
    if (contactInfo.address) {
      const requiredAddressFields = ['street', 'city', 'state', 'postalCode'];
      const missingFields = requiredAddressFields.filter(field => !contactInfo.address[field]);
      if (missingFields.length > 0) {
        console.log(`[${traceId}] ⚠️ Address missing fields: ${missingFields.join(', ')} - using defaults`);
        // Don't fail, just log warning - can use defaults
      }
    }

    // ========== EXTRACT AND VALIDATE GST DATA ==========
    const gstData = req.body.gstData || req.body.gst || null;
    
    const uid = req.body.uid || null;
    console.log(`[${traceId}] 👤 uid: ${uid}`);
     
    if (gstData) {
      console.log(`[${traceId}] 🧾 GST Data provided:`, {
        gstn: gstData.gstn || gstData.number,
        gsta: (gstData.gsta || gstData.legalName || gstData.businessName)?.substring(0, 30),
        gstp: gstData.gstp || gstData.phone,
        gste: gstData.gste || gstData.email
      });
      
      // Validate GST data
      const gstValidation = validateGSTData(gstData);
      if (!gstValidation.isValid) {
        return res.status(400).json({
          success: false,
          traceId,
          message: "GST Data validation failed",
          errors: gstValidation.errors
        });
      }
      
      // Convert GSTE email to GDS format before passing to service
      if (gstData.gste || gstData.email) {
        const rawEmail = gstData.gste || gstData.email;
        const gdsEmail = convertEmailToGDSFormat(rawEmail);
        if (gstData.gste) gstData.gste = gdsEmail;
        else gstData.email = gdsEmail;
        console.log(`[${traceId}] 📧 GSTE email converted to GDS format: ${gdsEmail}`);
      }
      
      console.log(`[${traceId}] ✅ GST data validated successfully`);
    } else {
      console.log(`[${traceId}] ℹ️ No GST data provided, proceeding without GST SSRs`);
    }

    // 6. Build passenger key map from pricing response
    const passengerKeysMap = {};
    const passengerKeyByType = {};
    
    for (const pk of req.body.passengerKeys) {
      passengerKeysMap[pk.code] = pk;
      passengerKeyByType[pk.code] = pk.key;
      console.log(`[${traceId}] 📋 Pricing key available: ${pk.code} -> ${pk.key}`);
    }
    
    // 7. Validate each passenger and build enriched passenger array
    const paxCounts = { ADT: 0, CHD: 0, CNN: 0, INF: 0 };
    const enrichedPassengers = [];
    
    for (let i = 0; i < passengers.length; i++) {
      const p = passengers[i];
      const type = p.type?.toUpperCase();
      
      // Validate type
      if (!type || !VALID_PTC_CODES.includes(type)) {
        return res.status(400).json({
          success: false,
          traceId,
          message: `passengers[${i}]: invalid type "${p.type}". Valid: ADT, CHD, CNN, INF`
        });
      }
      
      // Check if passenger key exists for this type
      if (!passengerKeysMap[type]) {
        // For CNN, also check if CHD key exists (since some responses use CHD)
        if (type === "CNN" && passengerKeysMap["CHD"]) {
          console.log(`[${traceId}] ⚠️ Using CHD key for CNN passenger`);
        } else {
          return res.status(400).json({
            success: false,
            traceId,
            message: `No passenger key found for type "${type}" in pricing response. Available: ${Object.keys(passengerKeysMap).join(', ')}`
          });
        }
      }
      
      // Validate required fields
      if (!p.firstName || !p.lastName) {
        return res.status(400).json({
          success: false,
          traceId,
          message: `passengers[${i}]: firstName and lastName are required`
        });
      }
      
      if (!p.dob) {
        return res.status(400).json({
          success: false,
          traceId,
          message: `passengers[${i}]: dob is required (YYYY-MM-DD)`
        });
      }
      
      if (!p.gender) {
        return res.status(400).json({
          success: false,
          traceId,
          message: `passengers[${i}]: gender is required (M/F)`
        });
      }
      
      // Validate age based on passenger type
      const age = p.age || calculateAgeFromDOB(p.dob);
      
      if (type === "CHD" || type === "CNN") {
        if (age > 12) {
          return res.status(400).json({
            success: false,
            traceId,
            message: `passengers[${i}]: Child passenger age must be <= 12, got ${age}`
          });
        }
      }
      
      if (type === "INF") {
        if (age > 2) {
          return res.status(400).json({
            success: false,
            traceId,
            message: `passengers[${i}]: Infant passenger age must be <= 2, got ${age}`
          });
        }
        
        // For infants, we need to associate with an adult
        if (!p.associatedWith && passengers.length > 1) {
          // Find first adult to associate with
          const firstAdult = passengers.find(pa => pa.type === "ADT");
          if (firstAdult) {
            // Find the adult's key from passengerKeysMap
            const adultKey = passengerKeysMap["ADT"]?.key;
            if (adultKey) {
              p.associatedWith = adultKey;
              console.log(`[${traceId}] 👶 Associating infant with adult key: ${p.associatedWith}`);
            }
          }
        }
      }
      
      // Get the correct passenger key
      let passengerKey = passengerKeysMap[type]?.key;
      if (!passengerKey && type === "CNN" && passengerKeysMap["CHD"]) {
        passengerKey = passengerKeysMap["CHD"]?.key;
      }
      
      if (!passengerKey) {
        return res.status(400).json({
          success: false,
          traceId,
          message: `Cannot determine passenger key for type ${type}`
        });
      }
      
      // Enrich passenger with key and calculated age
      const isFirstPassenger = i === 0;
      
      enrichedPassengers.push({
        ...p,
        type,
        key: passengerKey,
        age: age || (type === "INF" ? 1 : type === "CHD" ? 10 : 40),
        country: p.country || "IN",
        nationality: p.nationality || "IN",
        // Use contactInfo for first passenger, otherwise use individual passenger values or defaults
        phone: isFirstPassenger && contactInfo.phone?.number 
          ? contactInfo.phone.number 
          : (p.phone || "123456789"),
        email: isFirstPassenger && contactInfo.email
          ? contactInfo.email
          : (p.email || `${p.firstName.toLowerCase()}.${p.lastName.toLowerCase()}@example.com`)
      });
      
      paxCounts[type]++;
    }
    
    // Validate at least one adult
    if (paxCounts.ADT === 0) {
      return res.status(400).json({
        success: false,
        traceId,
        message: "At least 1 ADT passenger is required"
      });
    }
    
    // Log summary
    console.log(`[${traceId}] ✅ Passenger Summary:`);
    console.log(`[${traceId}]    ADT: ${paxCounts.ADT}`);
    console.log(`[${traceId}]    CHD: ${paxCounts.CHD}`);
    console.log(`[${traceId}]    CNN: ${paxCounts.CNN}`);
    console.log(`[${traceId}]    INF: ${paxCounts.INF}`);
    console.log(`[${traceId}] 📋 Selected fare index: ${selectedFareIndex}`);
    
    // Log contact info if provided
    if (contactInfo.email) {
      console.log(`[${traceId}] 📧 Contact email: ${contactInfo.email}`);
    }
    if (contactInfo.phone?.number) {
      console.log(`[${traceId}] 📱 Contact phone: ${contactInfo.phone.number}`);
    }
    if (contactInfo.address) {
      console.log(`[${traceId}] 🏠 Contact address: ${contactInfo.address.city}, ${contactInfo.address.state}`);
    }
    
    // 8. Call the PNR creation service with contactInfo and gstData
    const result = await createPNR({
      traceId,
      selectedFareIndex,
      passengers: enrichedPassengers,
      passengerKeys: req.body.passengerKeys,
      pricingResponse: req.body.pricingResponse,
      contactInfo: contactInfo,
      gstData: gstData,
      uid: uid          // ✅ added
    });
    
    const duration = Date.now() - startTime;
    console.log(`[${traceId}] ✅ Booking completed in ${duration}ms`);
    
    return res.status(200).json(result);

  } catch (error) {
    console.error(`[${traceId}] ❌ Error:`, error.message);
    console.error(`[${traceId}] Stack:`, error.stack);
    return res.status(500).json({
      success: false,
      traceId,
      error: error.message,
      stack: process.env.NODE_ENV === 'development' ? error.stack : undefined
    });
  }
};

// Helper function to calculate age from DOB
function calculateAgeFromDOB(dobStr) {
  const today = new Date();
  const birthDate = new Date(dobStr);
  let age = today.getFullYear() - birthDate.getFullYear();
  const monthDiff = today.getMonth() - birthDate.getMonth();
  if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
    age--;
  }
  return age;
}

// ========== HELPER FUNCTIONS ==========
function isValidEmail(email) {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
}

// Validates both standard (a@b.com) and GDS format (a//b.com)
function isValidGSTEmail(email) {
  const standardRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  const gdsRegex = /^[^\s]+\/\/[^\s]+\.[^\s]+$/;
  return standardRegex.test(email) || gdsRegex.test(email);
}

// Converts standard email to GDS format: john@example.com -> john//example.com
function convertEmailToGDSFormat(email) {
  return email.replace('@', '//');
}

function isValidPhone(phone) {
  // Basic validation - at least 6 digits
  const phoneRegex = /^\d{6,15}$/;
  return phoneRegex.test(phone.toString().replace(/[+\-\s]/g, ''));
}

// ========== GST VALIDATION HELPER ==========
function isValidGSTN(gstn) {
  // GSTN format: 15 characters alphanumeric
  // Format: 2 digits state code + 10 digits PAN + 1 digit entity code + 1 digit Z + 1 digit checksum
  const gstnRegex = /^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}[Z]{1}[0-9A-Z]{1}$/;
  return gstnRegex.test(gstn);
}

function validateGSTData(gstData) {
  const errors = [];
  
  if (!gstData) return { isValid: true, errors: [] };
  
  // GSTN validation (required)
  if (gstData.gstn || gstData.number) {
    const gstn = gstData.gstn || gstData.number;
    if (!isValidGSTN(gstn)) {
      errors.push("Invalid GSTN format. Expected 15 characters alphanumeric in standard GST format (e.g., 36AACCH5485M1Z2)");
    }
  } else {
    errors.push("GSTN (gstn or number) is required for GST billing");
  }
  
  // GSTA - Legal Name (required)
  if (!gstData.gsta && !gstData.legalName && !gstData.businessName) {
    errors.push("GSTA (legal name) is required for GST billing");
  }
  
  // GSTP - Phone Number (required - this is customer's phone number for GST)
  if (gstData.gstp || gstData.phone) {
    const phone = gstData.gstp || gstData.phone;
    // Phone validation - 10-15 digits
    const phoneStr = phone.toString().replace(/[+\-\s]/g, '');
    if (!/^\d{10,15}$/.test(phoneStr)) {
      errors.push("GSTP should be a valid phone number (10-15 digits)");
    }
  } else {
    errors.push("GSTP (phone number) is required for GST billing");
  }
  
  // GSTE - Email (required) - accepts both standard and GDS format
  if (gstData.gste || gstData.email) {
    const email = gstData.gste || gstData.email;
    if (!isValidGSTEmail(email)) {
      errors.push("GSTE email format is invalid");
    }
  } else {
    errors.push("GSTE (email) is required for GST billing");
  }
  
  return { isValid: errors.length === 0, errors };
}