const tripsModel = require('../model/tripsModel');

exports.getAvailableTrips = async (req, res) => {
  try {

    const { source, destination, doj} = req.query;
    const { operator, bdPoint, dpPoint, AC, nonAC, seater, sleeper, priceSort, timeSort} = req.query;
    // console.log(operator, bdPoint, dpPoint, AC, nonAC, seater, sleeper, priceSort, timeSort);

    // Validate required fields
    const missingFields = [];
    if (!source) missingFields.push('source');
    if (!destination) missingFields.push('destination');
    if (!doj) missingFields.push('Date of Journey');
    if (missingFields.length > 0) {
      const errorMessage = missingFields.join(', ') + (missingFields.length > 1 ? ' are required' : ' is required');
      return res.status(400).json({ error: errorMessage });
    }

    // Trim inputs
    const trimmedSource = source.trim();
    const trimmedDestination = destination.trim();
    trimmedDoj = doj.trim();

    // Check source != destination
    if (trimmedSource.toLowerCase() === trimmedDestination.toLowerCase()) {
      return res.status(400).json({ error: 'Source and destination cannot be the same' });
    }

    // Validate date format
    if (!/^\d{4}-\d{2}-\d{2}$/.test(trimmedDoj)) {
      return res.status(400).json({ error: 'Invalid date format. Use YYYY-MM-DD.' });
    }

    // Split and parse date components
    const [yearStr, monthStr, dayStr] = trimmedDoj.split('-');
    const year = parseInt(yearStr, 10);
    const month = parseInt(monthStr, 10);
    const day = parseInt(dayStr, 10);

    // Check if components are valid numbers
    if (isNaN(year) || isNaN(month) || isNaN(day)) {
      return res.status(400).json({ error: 'Invalid date value' });
    }

    // Create and validate date in UTC
    const parsedDate = new Date(Date.UTC(year, month - 1, day));
    if (
      parsedDate.getUTCFullYear() !== year ||
      parsedDate.getUTCMonth() + 1 !== month ||
      parsedDate.getUTCDate() !== day
    ) {
      return res.status(400).json({ error: 'Invalid date value' });
    }

    // Check if date is in the past (UTC)
    const todayUTC = new Date();
    todayUTC.setUTCHours(0, 0, 0, 0);
    const travelDateUTC = new Date(parsedDate);
    travelDateUTC.setUTCHours(0, 0, 0, 0);
    if (travelDateUTC < todayUTC) {
      return res.status(400).json({ error: 'Travel date cannot be in the past' });
    }

    // Check if date is too far in the future (e.g., 6 months)
    const maxFutureDate = new Date();
    maxFutureDate.setUTCMonth(maxFutureDate.getUTCMonth() + 3);
    if (travelDateUTC > maxFutureDate) {
      return res.status(400).json({ error: 'Date cannot be more than 3 months in the future' });
    }

    // Normalize case for source and destination
    const normalizedSource = trimmedSource.toLowerCase();
    const normalizedDestination = trimmedDestination.toLowerCase();
    
    req.session.bus_booking = {
        source : normalizedSource,
        destination : normalizedDestination,
        date : trimmedDoj
    };

    // Fetch trips
    
    const tripsData = await tripsModel.fetchAvailableTrips(normalizedSource, normalizedDestination, trimmedDoj);

    if (!tripsData || tripsData.length === 0) {
      return res.status(404).json({ error: 'No trips available for the given parameters' });
    }

    let filteredTripsData = tripsData.availableTrips;
    
    if (operator != undefined) {
      // console.log("operator filtering start");
      filteredTripsData = filteredTripsData.filter(trip => 
        typeof trip.travels === 'string' && trip.travels.toLowerCase().includes(operator)
    );
    // filteredTripsData.forEach(element => {console.log("operator:", element.travels, element.busType)
    //   });
    };

    if (bdPoint !== undefined) {
    
      const lowerBdPoint = bdPoint.toLowerCase();
      // console.log(lowerBdPoint)
      filteredTripsData = filteredTripsData.filter(trip => {
        if (Array.isArray(trip.boardingTimes)) {
          return trip.boardingTimes.some(bt =>
            typeof bt.bpName === 'string' && bt.bpName.toLowerCase().includes(lowerBdPoint)
          );
        }
        else return false;
        
        });
    //   console.log(filteredTripsData.length)
    //   filteredTripsData.forEach(trip => {
    //     console.log("................................");
    //     trip.boardingTimes.forEach(bt => {
    //       console.log("Boarding Address:",bt.bpName);
    //     });
    //   });
    };


    if (dpPoint !== undefined) {
      const lowerDpPoint = dpPoint.toLowerCase();
      // console.log(lowerDpPoint)
    
      filteredTripsData = filteredTripsData.filter(trip => {
        if (Array.isArray(trip.droppingTimes)) {
    
          return trip.droppingTimes.some(bt =>
            typeof bt.bpName === 'string' && bt.bpName.toLowerCase().includes(lowerDpPoint)
          );
        }
        else return false;
        
      });
    //   console.log(filteredTripsData.length)
    //   filteredTripsData.forEach(trip => {
    //     console.log("................................");
    //     trip.droppingTimes.forEach(dp => {
    //       console.log("dropping Address:",dp.bpName);
    //     });
    //   });
    };
    
    if (AC || nonAC) {
    // console.log("Filtering AC and/or nonAC trips");
    // console.log("AC:", AC, "nonAC:", nonAC);

    filteredTripsData = filteredTripsData.filter(trip => {
    const isAC = trip.AC?.toLowerCase() === "true";
    const isNonAC = trip.nonAC?.toLowerCase() === "true";

    const applyAC = AC?.toLowerCase() === "true";
    const applyNonAC = nonAC?.toLowerCase() === "true";

    // Logic:
    // - if both ac and nonAc are true: keep trip if AC or nonAC is true
    // - if only ac: keep if AC is true
    // - if only nonAc: keep if nonAC is true

    if (applyAC && applyNonAC) return isAC || isNonAC;
    if (applyAC) return isAC;
    if (applyNonAC) return isNonAC;

    return true; // no filter, keep all
  });

//   filteredTripsData.forEach(trip => {
//     console.log("Trip:", trip.travels, "AC:", trip.AC, "||nonAC:", trip.nonAC);
    
//   });
//   console.log(filteredTripsData.length);
}

    if (seater) {
      // console.log("AC/Non AC  filtering start");
      filteredTripsData = filteredTripsData.filter(trip => 
      typeof trip.seater === 'string' && trip.seater.toLowerCase()=== (seater)
      );
      // filteredTripsData.forEach(element => {console.log(element.travels, element.seater)
      // });
    };

    if (sleeper) {
      // console.log("AC/Non AC  filtering start");
      filteredTripsData = filteredTripsData.filter(trip => 
      typeof trip.sleeper === 'string' && trip.sleeper.toLowerCase()=== (sleeper)
      );
      // filteredTripsData.forEach(element => {console.log(element.travels, element.sleeper)
      // });
    };


    // Sorting on the basis of Price
    if (priceSort === 'ASC' || priceSort === 'DESC') {
      const sortOrder = priceSort === 'DESC' ? 'DESC' : 'ASC';

      // Helper function to get the relevant fare from the trip (min or max)
      function getComparableFare(fares, order = 'ASC') {
        if (Array.isArray(fares)) {
          const numericFares = fares.map(f => parseFloat(f)).filter(f => !isNaN(f));
          if (!numericFares.length) return Number.MAX_VALUE; // fallback
        return priceSort === 'ASC' ? Math.min(...numericFares) : Math.min(...numericFares);
        } else {
        const singleFare = parseFloat(fares);
        return isNaN(singleFare) ? Number.MAX_VALUE : singleFare;
  }
}

      filteredTripsData.sort((a, b) => {
      const fareA = getComparableFare(a.fares, sortOrder);
      const fareB = getComparableFare(b.fares, sortOrder);

      return priceSort === 'ASC' ? fareA - fareB : fareB - fareA;
      });
    }

         // Sorting on the basis of departure time
    if (timeSort === 'ASC' || timeSort === 'DESC') {
        filteredTripsData = filteredTripsData.filter(trip =>
        parseFloat(trip.departureTime) < 1440);
        filteredTripsData.sort((a, b) => {
        const depTimeA = parseFloat(a.departureTime);
        const depTimeB = parseFloat(b.departureTime);
        return timeSort === 'ASC' ? depTimeA - depTimeB : depTimeB - depTimeA;
      });
      filteredTripsData.forEach(element => {console.log(element.travels, element.departureTime)})
    }

    
    res.json({availableTrips:filteredTripsData});
  } catch (error) {
    console.error('Error fetching available trips:', error);
    res.status(500).json({ error: 'Failed to fetch available trips' });
  }
};

