/**
 * SEO Service
 * Business logic for SEO landing pages (Intercity Routes, Airport Routes, City Taxi Services)
 * Uses dynamic pricing from BookingService.calculateFare()
 */

const mongoose = require('mongoose');
const IntercityRoute = require('../models/intercity-route.model');
const AirportRoute = require('../models/airport-route.model');
const CityTaxi = require('../models/city-taxi.model');
const VehicleGroup = require('../models/vehicle-group.model');
const Zone = require('../models/zone.model');
const bookingService = require('./booking.service');
const mapService = require('./map.service');
const Vehicle = require('../models/vehicle.model');
const VehicleModel = require('../models/vehicle-model.model');

// ==========================================
// DYNAMIC PRICING UTILITIES
// ==========================================

/**
 * Calculate "Starts From" price using the cheapest VehicleGroup
 */
exports.calculateDynamicPricing = async (zoneId, tripType = 'oneWay', distance = 0) => {
    // Get zone for extra fare rules
    const zone = await Zone.findById(zoneId).lean();
    if (!zone) {
        return { startsFrom: 0, vehicleOptions: [] };
    }

    // Get all active VehicleGroups with fuel pricing
    const vehicleGroups = await VehicleGroup.find({
        status: 'active',
        'fuelPricing.0': { $exists: true }
    })
        .populate('category', 'categoryName')
        .sort({ 'fuelPricing.0.acBaseFare': 1 })
        .lean();

    if (!vehicleGroups.length) {
        return { startsFrom: 0, vehicleOptions: [] };
    }

    const vehicleOptions = [];

    for (const group of vehicleGroups) {
        // Check if there is at least one AVAILABLE vehicle in this group & zone
        // Must match booking service criteria: operationalStatus='active' AND bookingStatus='available'
        const activeVehicles = await Vehicle.find({
            group: group._id,
            zone: zoneId,
            operationalStatus: 'active',
            bookingStatus: 'available'
        }).select('model fuelType').lean();

        // Get unique model IDs from active vehicles
        const modelIds = [...new Set(activeVehicles.map(v => v.model).filter(m => m))];

        // Fetch model details
        const models = await VehicleModel.find({ _id: { $in: modelIds } })
            .select('modelName vehicleImages')
            .lean();

        // Build model names array (without brand)
        const modelNames = models.map(m => m.modelName || '').filter(n => n);

        // Use first model for primary display
        const primaryModel = models[0] || {};
        const displayName = modelNames.length > 0 ? modelNames.join(', ') : (group.groupName || 'Standard');

        // Get front image from model or group
        const modelImages = primaryModel.vehicleImages || [];
        const frontImage = modelImages.find(img => img.view === 'front')?.url
            || modelImages[0]?.url
            || group.vehicleImages?.frontView
            || null;

        let minPrice = Infinity;
        let bestFuelType = 'petrol';
        let bestPricingRaw = null;
        let bestFare = null;
        // let ratePerKm = 0

        for (const pricing of group.fuelPricing || []) {
            const fare = bookingService.calculateFare(tripType, {
                distance,
                stopsCount: 0,
                totalWaitTime: 0,
                rentalPackage: null,
                group,
                zone,
                fuelType: pricing.fuelType,
                isAc: true,
                scheduledTime: (function () { const d = new Date(); d.setHours(12, 0, 0, 0); return d; })() // Use 12:00 PM to avoid night charges in "Starts From"
            });

            if (fare.total < minPrice) {
                minPrice = fare.total;
                bestFuelType = pricing.fuelType;
                bestPricingRaw = pricing;
                bestFare = fare;

            }
        }

        // Use ratePerKm from fare calculation (already considers AC/Non-AC based on isAc: true)
        const baseKm = bestPricingRaw ? (bestPricingRaw.baseKm || 0) : 0;
        const extraFarePerKm = bestFare ? (bestFare.ratePerKm || 0) : 0;
        const waitingCharge = bestPricingRaw ? (bestPricingRaw.waitingCharge || 0) : 0;

        vehicleOptions.push({
            groupId: group._id,
            modelId: primaryModel._id || null,
            groupName: group.groupName,
            displayName: displayName,
            modelNames: modelNames.length > 0 ? modelNames : [displayName],
            tier: group.tier,
            seats: group.seats,
            category: group.category?.categoryName || 'Standard',
            price: minPrice === Infinity ? 0 : minPrice,
            fuelType: bestFuelType,
            image: frontImage,
            cancellationPolicy: group.cancellationPolicy,
            // Added Details for SEO/UI (Goibibo style)
            includedKm: distance,
            extraFarePerKm: extraFarePerKm,
            waitingCharge: waitingCharge,
            estimatedTax: Math.round(minPrice * 0.05), // Example: 5% tax estimation (can be adjusted based on settings if needed)
        });
    }

    vehicleOptions.sort((a, b) => a.price - b.price);

    return {
        startsFrom: vehicleOptions.length > 0 ? vehicleOptions[0].price : 0,
        vehicleOptions
    };
};

/**
 * Internal helper to generate default FAQs for Intercity Routes
 */
const _generateDefaultIntercityFAQs = (originCity, destinationCity, distance, duration, startsFrom, vehicleOptions) => {
    const cheapestCategory = vehicleOptions && vehicleOptions.length > 0 ? vehicleOptions[0].category : 'Hatchback';
    const hours = duration ? Math.ceil(duration / 60) : 0;

    return [
        {
            question: `What are the advantages of online cab booking from our platform?`,
            answer: `Online cab booking not only helps you with best prices but also helps you with the convenience of paying through multiple payment options (like Debit Card, Credit Card, eWallets etc.). You can easily compare prices and choose various categories of cabs like Hatchback cars, Sedan and SUV. Book now`
        },
        {
            question: `What is the ${originCity} to ${destinationCity} cab/taxi fare?`,
            answer: `The starting fare for a ${originCity} to ${destinationCity} cab is ₹${startsFrom}. We offer competitive rates and transparent pricing with no hidden charges.`
        },
        {
            question: `What is the distance from ${originCity} to ${destinationCity} by car?`,
            answer: `The distance from ${originCity} to ${destinationCity} by car is approximately ${distance} km. The estimated travel time is around ${hours} hours, depending on traffic conditions.`
        },
        {
            question: `Can I Book a one way cab from ${originCity} to ${destinationCity}?`,
            answer: `Yes, you can book a one-way cab from ${originCity} to ${destinationCity}. We provide reliable one-way taxi services for a comfortable and hassle-free journey.`
        },
        {
            question: `Which is the most economical cab available in ${originCity}?`,
            answer: `The most economical cab available in ${originCity} is currently the ${cheapestCategory} category. You can choose from various vehicle options based on your budget and requirements.`
        }
    ];
};

/**
 * Helper to format duration in minutes to "X hours Y mins"
 */
const _formatDuration = (durationInMinutes) => {
    if (!durationInMinutes) return '0 mins';
    const hours = Math.floor(durationInMinutes / 60);
    const mins = durationInMinutes % 60;
    return hours > 0
        ? `${hours} hour${hours > 1 ? 's' : ''} ${mins > 0 ? mins + ' mins' : ''}`.trim()
        : `${mins} mins`;
};

/**
 * Helper to automatically enrich route data with coordinates and distance/duration
 * @param {string} type - 'intercity', 'airport', or 'city'
 * @param {object} data - The data object to enrich (will be modified in-place)
 * @param {object} existing - Existing document data (optional, for updates)
 */
const _enrichRouteData = async (type, data, existing = {}) => {
    try {
        const merged = { ...existing, ...data };

        if (type === 'intercity') {
            const needsStats = !merged.distance || merged.distance === 0 || !merged.duration || merged.duration === 0;
            const citiesChanged = !!(data.originCity || data.destinationCity);
            const isDistanceProvided = data.distance && data.distance > 0;

            if (citiesChanged || !merged.originCoordinates || !merged.destinationCoordinates) {
                const originCoords = await mapService.getCoordinates(merged.originCity);
                const destCoords = await mapService.getCoordinates(merged.destinationCity);

                if (originCoords.lat !== 0) {
                    data.originCoordinates = { type: 'Point', coordinates: [originCoords.lng, originCoords.lat] };
                }
                if (destCoords.lat !== 0) {
                    data.destinationCoordinates = { type: 'Point', coordinates: [destCoords.lng, destCoords.lat] };
                }
            }

            if (merged.originCity && merged.destinationCity && !isDistanceProvided && (needsStats || citiesChanged)) {
                const stats = await mapService.getDistanceAndDuration(merged.originCity, merged.destinationCity);
                if (stats.distance > 0) {
                    data.distance = stats.distance;
                    data.duration = stats.duration;
                } else if (data.originCoordinates && data.destinationCoordinates) {
                    // Use async Google Maps distance calculation as fallback
                    try {
                        const result = await bookingService.calculateDistanceAsync(
                            data.originCoordinates.coordinates[1], data.originCoordinates.coordinates[0],
                            data.destinationCoordinates.coordinates[1], data.destinationCoordinates.coordinates[0]
                        );
                        data.distance = result.distance;
                        data.duration = result.duration;
                    } catch (err) {
                        // Final fallback to sync method with road factor
                        const distance = bookingService.calculateDistance(
                            data.originCoordinates.coordinates[1], data.originCoordinates.coordinates[0],
                            data.destinationCoordinates.coordinates[1], data.destinationCoordinates.coordinates[0]
                        );
                        data.distance = Math.round(distance);
                        data.duration = Math.round(distance / 40 * 60);
                    }
                }
            }
        } else if (type === 'airport') {
            const needsStats = !merged.distance || merged.distance === 0 || !merged.duration || merged.duration === 0;
            const detailsChanged = !!(data.airportName || data.cityName);
            const isDistanceProvided = data.distance && data.distance > 0;

            if (detailsChanged || !merged.coordinates || !merged.cityCoordinates) {
                // Append "India" to ensure we get results within the country
                const airportQuery = merged.airportName.toLowerCase().includes('india') ? merged.airportName : `${merged.airportName}, India`;
                const cityQuery = merged.cityName.toLowerCase().includes('india') ? merged.cityName : `${merged.cityName}, India`;

                const airportCoords = await mapService.getCoordinates(airportQuery);
                if (airportCoords.lat !== 0) {
                    data.coordinates = { type: 'Point', coordinates: [airportCoords.lng, airportCoords.lat] };
                }
                const cityCoords = await mapService.getCoordinates(cityQuery);
                if (cityCoords.lat !== 0) {
                    data.cityCoordinates = { type: 'Point', coordinates: [cityCoords.lng, cityCoords.lat] };
                }
            }

            if (merged.airportName && merged.cityName && !isDistanceProvided && (needsStats || detailsChanged)) {
                const stats = await mapService.getDistanceAndDuration(merged.airportName, merged.cityName);
                if (stats.distance > 0) {
                    data.distance = stats.distance;
                    data.duration = stats.duration;
                } else if (data.coordinates && data.cityCoordinates) {
                    // Use async Google Maps distance calculation as fallback
                    try {
                        const result = await bookingService.calculateDistanceAsync(
                            data.coordinates.coordinates[1], data.coordinates.coordinates[0],
                            data.cityCoordinates.coordinates[1], data.cityCoordinates.coordinates[0]
                        );
                        data.distance = result.distance;
                        data.duration = result.duration;
                    } catch (err) {
                        // Final fallback to sync method with road factor
                        const distance = bookingService.calculateDistance(
                            data.coordinates.coordinates[1], data.coordinates.coordinates[0],
                            data.cityCoordinates.coordinates[1], data.cityCoordinates.coordinates[0]
                        );
                        data.distance = Math.round(distance);
                        data.duration = Math.round(distance / 40 * 60);
                    }
                } else if (data.coordinates) {
                    // Fallback if cityCoordinates missing
                    const cityCoords = await mapService.getCoordinates(merged.cityName);
                    if (cityCoords.lat !== 0) {
                        try {
                            const result = await bookingService.calculateDistanceAsync(
                                data.coordinates.coordinates[1], data.coordinates.coordinates[0],
                                cityCoords.lat, cityCoords.lng
                            );
                            data.distance = result.distance;
                            data.duration = result.duration;
                        } catch (err) {
                            const distance = bookingService.calculateDistance(
                                data.coordinates.coordinates[1], data.coordinates.coordinates[0],
                                cityCoords.lat, cityCoords.lng
                            );
                            data.distance = Math.round(distance);
                            data.duration = Math.round(distance / 40 * 60);
                        }
                    }
                }
            }
        } else if (type === 'city') {
            if (data.cityName || !merged.coordinates) {
                const cityCoords = await mapService.getCoordinates(merged.cityName);
                if (cityCoords.lat !== 0) {
                    data.coordinates = { type: 'Point', coordinates: [cityCoords.lng, cityCoords.lat] };
                }
            }
        }
    } catch (error) {
        console.error(`Error enriching ${type} route data:`, error.message);
    }
};

// ==========================================
// INTERCITY ROUTES
// ==========================================

exports.getIntercityRoutes = async (filters = {}, pagination = {}) => {
    const { isActive, search } = filters;
    const { page = 1, limit = 20 } = pagination;
    const skip = (page - 1) * limit;

    const query = {};
    if (isActive !== undefined) query.isActive = isActive;
    if (search) {
        query.$or = [
            { originCity: { $regex: search, $options: 'i' } },
            { destinationCity: { $regex: search, $options: 'i' } },
            { slug: { $regex: search, $options: 'i' } }
        ];
    }

    const [routes, total] = await Promise.all([
        IntercityRoute.find(query)
            .populate('zone', 'zoneName')
            .sort({ displayOrder: 1, createdAt: -1 })
            .skip(skip)
            .limit(parseInt(limit))
            .lean(),
        IntercityRoute.countDocuments(query)
    ]);

    const routesWithPricing = await Promise.all(
        routes.map(async (route) => {
            // Skip pricing calculation if zone is missing
            if (!route.zone) {
                return { ...route, startsFrom: 0 };
            }
            const { startsFrom } = await exports.calculateDynamicPricing(
                route.zone._id || route.zone,
                'oneWay',
                route.distance
            );
            return {
                ...route,
                startsFrom
            };
        })
    );

    return {
        routes: routesWithPricing,
        pagination: {
            page: parseInt(page),
            limit: parseInt(limit),
            total,
            pages: Math.ceil(total / limit)
        }
    };
};

exports.getIntercityRouteBySlug = async (slug, isActive = true) => {
    // Build query - only add isActive filter if explicitly provided
    const query = { slug };
    if (isActive !== undefined && isActive !== null) {
        query.isActive = isActive;
    }

    const route = await IntercityRoute.findOne(query)
        .populate('zone', 'zoneName zoneAddress')
        .lean();

    if (!route) {
        throw { message: 'Route not found', statusCode: 404 };
    }
    // 2. Define "Related" Queries
    // Query A: Other routes from the SAME Origin (e.g., Delhi -> Agra, Delhi -> Manali)
    // We exclude the current route's destination to avoid duplicates.
    const nearbyRoutesPromise = IntercityRoute.find({
        originCity: { $regex: new RegExp(`^${route.originCity}$`, 'i') }, // Case-insensitive match
        destinationCity: { $ne: route.destinationCity }, // Not the current destination
        isActive: true
    })
        .select('originCity destinationCity slug distance duration zone') // Fetch only needed fields
        .limit(6) // Limit to 6 suggestions
        .lean();

    // Query B: Inward routes from the Destination (e.g., Jaipur -> Ajmer, Jaipur -> Udaipur)
    // Wait... Inward means routes COMING TO destination? The previous comment said "Jaipur -> Ajmer" which is FROM Destination.
    // Let's stick to the requested names:
    // 1. "Nearby Routes" (Already implemented: From Origin to other places)
    // 2. "Inward Routes" (Routes ending at the same destination from other origins? Or routes starting from destination?)
    // Re-reading user request image 2 "Cabs from Delhi" (Origin) and "Cabs to Jaipur" (Destination).

    // Existing "nearbyRoutesPromise" finds routes from SAME Origin. (e.g. Delhi -> Agra). This matches "Cabs from Delhi".
    // Existing "inwardRoutesPromise" finds routes where destination is current destination (e.g. Agra -> Jaipur). This is "Cabs to Jaipur". (Actually the code below had destinationCity regex same as current destination).

    // Let's rename for clarity to match user Request Image 2 logic if needed, but the logic seems close.
    // However, I need to add explicit "Cabs from Destination" (Routes starting from the destination city).
    // And "Cabs to Origin" (Routes ending at the origin city).

    const existingNearbyRoutesPromise = IntercityRoute.find({
        originCity: { $regex: new RegExp(`^${route.originCity}$`, 'i') },
        destinationCity: { $ne: route.destinationCity },
        isActive: true
    }).select('originCity destinationCity slug distance duration zone').limit(6).lean();

    const existingInwardRoutesPromise = IntercityRoute.find({
        destinationCity: { $regex: new RegExp(`^${route.destinationCity}$`, 'i') },
        originCity: { $ne: route.originCity },
        isActive: true
    }).select('originCity destinationCity slug distance duration zone').limit(6).lean();

    // New Requirements from Image 2:
    // "Cabs to [Origin]" -> Routes where destination is the current Origin.
    const routesToOriginPromise = IntercityRoute.find({
        destinationCity: { $regex: new RegExp(`^${route.originCity}$`, 'i') },
        originCity: { $ne: route.destinationCity },
        isActive: true
    }).select('slug originCity destinationCity').limit(6).lean();

    // "Cabs from [Destination]" -> Routes where origin is the current Destination.
    const routesFromDestinationPromise = IntercityRoute.find({
        originCity: { $regex: new RegExp(`^${route.destinationCity}$`, 'i') },
        destinationCity: { $ne: route.originCity },
        isActive: true
    }).select('slug originCity destinationCity').limit(6).lean();

    const [nearbyRoutesRaw, inwardRoutesRaw, routesToOriginRaw, routesFromDestinationRaw] = await Promise.all([
        existingNearbyRoutesPromise,
        existingInwardRoutesPromise,
        routesToOriginPromise,
        routesFromDestinationPromise
    ]);

    // 5. Helper to calculate price for related routes (So cards show "Starts ₹2500")
    // We use a simplified pricing logic here to save resources (e.g., just base price of cheapest car)
    const enrichWithPrice = async (routesList) => {
        return Promise.all(routesList.map(async (r) => {

            let price = 0;
            let details = {};
            if (r.zone) {
                const zoneId = r.zone._id || r.zone;
                const p = await exports.calculateDynamicPricing(zoneId, 'oneWay', r.distance);
                // console.log('p from seo service', p);
                price = p.startsFrom;
                // Extract additional details from the cheapest option
                if (p.vehicleOptions && p.vehicleOptions.length > 0) {
                    const cheapest = p.vehicleOptions[0];
                    details = {
                        includedKm: cheapest.includedKm,
                        extraFarePerKm: cheapest.extraFarePerKm,
                        estimatedTax: cheapest.estimatedTax
                    };
                }
            }
            return {
                ...r,
                startsFrom: price,
                durationText: _formatDuration(r.duration),
                ...details
            };
        }));
    };

    // 6. Enrich Related Routes with Prices
    // 6. Enrich Related Routes with Prices
    const nearbyRoutes = await enrichWithPrice(nearbyRoutesRaw);
    const inwardRoutes = await enrichWithPrice(inwardRoutesRaw);
    // const routesToOrigin = await enrichWithPrice(routesToOriginRaw);
    // const routesFromDestination = await enrichWithPrice(routesFromDestinationRaw);
    // Handle missing zone gracefully
    let startsFrom = 0;
    let vehicleOptions = [];
    if (route.zone) {
        const pricing = await exports.calculateDynamicPricing(
            route.zone._id || route.zone,
            'oneWay',
            route.distance
        );
        startsFrom = pricing.startsFrom;
        vehicleOptions = pricing.vehicleOptions;
    }

    // Format coordinates for frontend (GeoJSON [lng, lat] -> {lat, lng})
    const originCoords = route.originCoordinates?.coordinates?.length === 2
        ? { lat: route.originCoordinates.coordinates[1], lng: route.originCoordinates.coordinates[0] }
        : { lat: 0, lng: 0 };

    const destCoords = route.destinationCoordinates?.coordinates?.length === 2
        ? { lat: route.destinationCoordinates.coordinates[1], lng: route.destinationCoordinates.coordinates[0] }
        : { lat: 0, lng: 0 };

    return {
        ...route,
        originCoords,
        destCoords,
        startsFrom,
        durationText: _formatDuration(route.duration),
        vehicleOptions,
        nearbyRoutes,
        inwardRoutes,
        routesFromDestinationRaw,
        routesToOriginRaw
        // routesToOrigin,
        // routesFromDestination
    };
};

exports.createIntercityRoute = async (data, userId) => {
    const existing = await IntercityRoute.findOne({
        originCity: { $regex: new RegExp(`^${data.originCity}$`, 'i') },
        destinationCity: { $regex: new RegExp(`^${data.destinationCity}$`, 'i') }
    });

    if (existing) {
        throw { message: 'Route between these cities already exists', statusCode: 400 };
    }
    const zone = await Zone.findById(data.zone);
    if (!zone) {
        throw { message: 'Zone not found', statusCode: 404 };
    }

    const isManual = data.distance > 0;

    // Auto-fetch coordinates and distance/duration
    await _enrichRouteData('intercity', data);

    // Generate default FAQs if not provided or empty
    if (!data.faqs || data.faqs.length === 0) {
        const pricing = await exports.calculateDynamicPricing(data.zone, 'oneWay', data.distance);
        data.faqs = _generateDefaultIntercityFAQs(
            data.originCity,
            data.destinationCity,
            data.distance,
            data.duration,
            pricing.startsFrom,
            pricing.vehicleOptions
        );
    }

    // Auto-fetch coordinates and distance/duration
    await _enrichRouteData('intercity', data);

    const route = new IntercityRoute({
        ...data,
        isDistanceManual: data.distance > 0,
        createdBy: userId
    });

    await route.save();
    return route;
};

exports.updateIntercityRoute = async (id, data) => {
    const route = await IntercityRoute.findById(id);
    if (!route) {
        throw { message: 'Route not found', statusCode: 404 };
    }

    // Validate zone if it's being updated
    if (data.zone) {
        const zone = await Zone.findById(data.zone);
        if (!zone) {
            throw { message: 'Zone not found', statusCode: 404 };
        }
    }

    if (data.distance !== undefined && data.distance > 0) {
        data.isDistanceManual = true;
    }

    // Auto-fetch coordinates and distance/duration if cities changed
    if (data.originCity || data.destinationCity) {
        await _enrichRouteData('intercity', data, route.toObject());
    }

    Object.assign(route, data);
    await route.save();
    return route;
};

exports.deleteIntercityRoute = async (id) => {
    const route = await IntercityRoute.findByIdAndDelete(id);
    if (!route) {
        throw { message: 'Route not found', statusCode: 404 };
    }
    return route;
};

// ==========================================
// AIRPORT ROUTES
// ==========================================

exports.getAirportRoutes = async (filters = {}, pagination = {}) => {
    const { isActive, routeType, search } = filters;
    const { page = 1, limit = 20 } = pagination;
    const skip = (page - 1) * limit;

    const query = {};
    if (isActive !== undefined) query.isActive = isActive;
    if (routeType) query.routeType = routeType;
    if (search) {
        query.$or = [
            { airportName: { $regex: search, $options: 'i' } },
            { cityName: { $regex: search, $options: 'i' } },
            { slug: { $regex: search, $options: 'i' } }
        ];
    }

    const [routes, total] = await Promise.all([
        AirportRoute.find(query)
            .populate('zone', 'zoneName')
            .sort({ displayOrder: 1, createdAt: -1 })
            .skip(skip)
            .limit(parseInt(limit))
            .lean(),
        AirportRoute.countDocuments(query)
    ]);
    // console.log(routes);
    const routesWithPricing = await Promise.all(
        routes.map(async (route) => {
            // Skip pricing calculation if zone is missing
            if (!route.zone) {
                return { ...route, startsFrom: 0 };
            }
            const { startsFrom } = await exports.calculateDynamicPricing(
                route.zone._id || route.zone,
                'airport',
                route.distance
            );
            return {
                ...route,
                startsFrom
            };
        })
    );

    return {
        routes: routesWithPricing,
        pagination: {
            page: parseInt(page),
            limit: parseInt(limit),
            total,
            pages: Math.ceil(total / limit)
        }
    };
};

exports.getAirportRouteBySlug = async (slug) => {
    const route = await AirportRoute.findOne({ slug, isActive: true })
        .populate('zone', 'zoneName zoneAddress')
        .lean();

    if (!route) {
        throw { message: 'Airport route not found', statusCode: 404 };
    }

    // Handle missing zone gracefully
    let startsFrom = 0;
    let vehicleOptions = [];
    if (route.zone) {
        const pricing = await exports.calculateDynamicPricing(
            route.zone._id || route.zone,
            'airport',
            route.distance
        );
        startsFrom = pricing.startsFrom;
        vehicleOptions = pricing.vehicleOptions;
    }

    return {
        ...route,
        startsFrom,
        durationText: _formatDuration(route.duration),
        vehicleOptions
    };
};

exports.createAirportRoute = async (data, userId) => {

    const zone = await Zone.findById(data.zone);
    if (!zone) {
        throw { message: 'Zone not found', statusCode: 404 };
    }
    const existing = await AirportRoute.findOne({
        airportName: { $regex: new RegExp(`^${data.airportName}$`, 'i') },
        cityName: { $regex: new RegExp(`^${data.cityName}$`, 'i') },
        routeType: data.routeType
    });

    if (existing) {
        throw { message: 'This airport route already exists', statusCode: 400 };
    }

    // Auto-fetch coordinates and distance/duration
    await _enrichRouteData('airport', data);

    const route = new AirportRoute({
        ...data,
        isDistanceManual: data.distance > 0,
        createdBy: userId
    });

    await route.save();
    return route;
};

exports.updateAirportRoute = async (id, data) => {
    const route = await AirportRoute.findById(id);
    if (!route) {
        throw { message: 'Airport route not found', statusCode: 404 };
    }

    // Validate zone if it's being updated
    if (data.zone) {
        const zone = await Zone.findById(data.zone);
        if (!zone) {
            throw { message: 'Zone not found', statusCode: 404 };
        }
    }

    if (data.distance !== undefined && data.distance > 0) {
        data.isDistanceManual = true;
    }

    // Auto-fetch coordinates and distance/duration if airport/city changed
    if (data.airportName || data.cityName) {
        await _enrichRouteData('airport', data, route.toObject());
    }

    Object.assign(route, data);
    await route.save();
    return route;
};

exports.deleteAirportRoute = async (id) => {
    const route = await AirportRoute.findByIdAndDelete(id);
    if (!route) {
        throw { message: 'Airport route not found', statusCode: 404 };
    }
    return route;
};

// ==========================================
// CITY TAXI SERVICES
// ==========================================

exports.getCityTaxiServices = async (filters = {}, pagination = {}) => {
    const { isActive, search } = filters;
    const { page = 1, limit = 20 } = pagination;
    const skip = (page - 1) * limit;

    const query = {};
    if (isActive !== undefined) query.isActive = isActive;
    if (search) {
        query.$or = [
            { cityName: { $regex: search, $options: 'i' } },
            { slug: { $regex: search, $options: 'i' } }
        ];
    }

    const [services, total] = await Promise.all([
        CityTaxi.find(query)
            .populate('zone', 'zoneName')
            .sort({ displayOrder: 1, createdAt: -1 })
            .skip(skip)
            .limit(parseInt(limit))
            .lean(),
        CityTaxi.countDocuments(query)
    ]);

    const servicesWithPricing = await Promise.all(
        services.map(async (service) => {
            // Skip pricing calculation if zone is missing
            if (!service.zone) {
                return { ...service, startsFrom: 0 };
            }
            const { startsFrom } = await exports.calculateDynamicPricing(
                service.zone._id || service.zone,
                'oneWay',
                10  // Base 10km for "Starts From" display
            );
            return {
                ...service,
                startsFrom
            };
        })
    );

    return {
        services: servicesWithPricing,
        pagination: {
            page: parseInt(page),
            limit: parseInt(limit),
            total,
            pages: Math.ceil(total / limit)
        }
    };
};

/**
 * Get single city taxi service by slug with comprehensive data (9 sections)
 */
exports.getCityTaxiServiceBySlug = async (slug) => {
    // 1. Fetch the City Taxi Service
    const service = await CityTaxi.findOne({ slug, isActive: true })
        .populate('zone', 'zoneName zoneAddress')
        .lean();

    if (!service) {
        throw { message: 'City taxi service not found', statusCode: 404 };
    }

    // 2. Calculate base pricing for city (10km local)
    let startsFrom = 0;
    let vehicleOptions = [];
    if (service.zone) {
        const pricing = await exports.calculateDynamicPricing(
            service.zone._id || service.zone,
            'oneWay',
            10
        );
        startsFrom = pricing.startsFrom;
        vehicleOptions = pricing.vehicleOptions;
    }

    // 3. Format city coordinates
    const formattedCityCoords = {
        lat: service.coordinates?.coordinates ? service.coordinates.coordinates[1] : 0,
        lng: service.coordinates?.coordinates ? service.coordinates.coordinates[0] : 0
    };

    // === SECTION 1 & 6: Routes FROM City ===
    const routesFromCityRaw = await IntercityRoute.find({
        originCity: { $regex: new RegExp(`^${service.cityName}$`, 'i') },
        isActive: true
    })
        .select('originCity destinationCity slug distance duration zone')
        .sort({ displayOrder: 1, distance: 1 })
        .limit(30)
        .lean();

    // Enrich top 10 for detailed cards
    const enrichWithPriceHelper = async (routes, limit = 10) => {
        const enrichedRoutes = await Promise.all(routes.slice(0, limit).map(async (r) => {
            let price = 0;
            let details = {};
            if (r.zone) {
                const zoneId = r.zone._id || r.zone;
                const p = await exports.calculateDynamicPricing(zoneId, 'oneWay', r.distance);
                price = p.startsFrom;
                if (p.vehicleOptions && p.vehicleOptions.length > 0) {
                    const cheapest = p.vehicleOptions[0];
                    details = {
                        includedKm: cheapest.includedKm,
                        extraFarePerKm: cheapest.extraFarePerKm,
                        estimatedTax: cheapest.estimatedTax
                    };
                }
            }
            return {
                ...r,
                startsFrom: price,
                durationText: _formatDuration(r.duration),
                ...details
            };
        }));
        return enrichedRoutes;
    };

    const routesFromCity = await enrichWithPriceHelper(routesFromCityRaw, 10);
    const routesFromCitySlugsOnly = routesFromCityRaw.map(r => ({
        slug: r.slug,
        originCity: r.originCity,
        destinationCity: r.destinationCity
    }));

    // === SECTION 2 & 7: Routes TO City ===
    const routesToCityRaw = await IntercityRoute.find({
        destinationCity: { $regex: new RegExp(`^${service.cityName}$`, 'i') },
        isActive: true
    })
        .select('originCity destinationCity slug distance duration zone')
        .sort({ displayOrder: 1, distance: 1 })
        .limit(30)
        .lean();

    const routesToCity = await enrichWithPriceHelper(routesToCityRaw, 10);
    const routesToCitySlugsOnly = routesToCityRaw.map(r => ({
        slug: r.slug,
        originCity: r.originCity,
        destinationCity: r.destinationCity
    }));

    // === SECTION 8 & 9: Airport Routes ===
    const airportRoutesFrom = await AirportRoute.find({
        routeType: 'from_airport',
        cityName: { $regex: new RegExp(`^${service.cityName}$`, 'i') },
        isActive: true
    })
        .select('slug airportName cityName')
        .limit(15)
        .lean();

    const airportRoutesTo = await AirportRoute.find({
        routeType: 'to_airport',
        cityName: { $regex: new RegExp(`^${service.cityName}$`, 'i') },
        isActive: true
    })
        .select('slug airportName cityName')
        .limit(15)
        .lean();

    // === SECTION 3 & 5: Rental Packages ===
    const vehicleGroups = await VehicleGroup.find({
        status: 'active',
        'rentalPricing.0': { $exists: true }
    })
        .populate('category', 'categoryName')
        .sort({ tier: 1 })
        .lean();

    const rentalPackages = [];
    for (const group of vehicleGroups) {
        // Check if vehicles exist in this zone
        const vehiclesCount = await Vehicle.countDocuments({
            group: group._id,
            zone: service.zone._id || service.zone,
            $or: [{ status: 'active' }, { operationalStatus: 'active' }]
        });

        if (vehiclesCount === 0) continue;

        const packages = (group.rentalPricing || []).map(rp => ({
            hours: rp.hours,
            baseKm: rp.baseKm,
            price: Math.round(rp.baseFare),
            extraFarePerKm: rp.extraFarePerKm,
            fuelType: rp.fuelType
        }));

        if (packages.length > 0) {
            rentalPackages.push({
                groupId: group._id,
                groupName: group.groupName,
                tier: group.tier,
                seats: group.seats,
                category: group.category?.categoryName || 'Standard',
                packages: packages
            });
        }
    }

    // === SECTION 4: FAQs (from city-taxi model) ===
    const faqs = service.faqs || [];

    return {
        ...service,
        coordinates: formattedCityCoords,
        startsFrom,
        vehicleOptions,

        // 9 Data Sections
        routesFromCity,              // 1. Detailed cards FROM city
        routesToCity,                // 2. Detailed cards TO city
        rentalPackages,              // 3. Rental packages with pricing
        faqs,                        // 4. City-specific FAQs
        rentalPricingTable: rentalPackages, // 5. Rental pricing table (same as #3)
        routesFromCitySlugsOnly,     // 6. Slug-only links FROM city
        routesToCitySlugsOnly,       // 7. Slug-only links TO city
        airportRoutesFrom,           // 8. Airport routes FROM city
        airportRoutesTo              // 9. Airport routes TO city
    };
};

exports.createCityTaxiService = async (data, userId) => {
    const zone = await Zone.findById(data.zone);
    if (!zone) {
        throw { message: 'Zone not found', statusCode: 404 };
    }
    const existing = await CityTaxi.findOne({
        cityName: { $regex: new RegExp(`^${data.cityName}$`, 'i') }
    });

    if (existing) {
        throw { message: 'City taxi service already exists for this city', statusCode: 400 };
    }

    // Auto-fetch coordinates
    await _enrichRouteData('city', data);

    const service = new CityTaxi({
        ...data,
        createdBy: userId
    });

    await service.save();
    return service;
};

exports.updateCityTaxiService = async (id, data) => {
    const service = await CityTaxi.findById(id);
    if (!service) {
        throw { message: 'City taxi service not found', statusCode: 404 };
    }

    // Validate zone if it's being updated
    if (data.zone) {
        const zone = await Zone.findById(data.zone);
        if (!zone) {
            throw { message: 'Zone not found', statusCode: 404 };
        }
    }

    // Auto-fetch coordinates if city changed
    if (data.cityName) {
        await _enrichRouteData('city', data, service.toObject());
    }

    Object.assign(service, data);
    await service.save();
    return service;
};

exports.deleteCityTaxiService = async (id) => {
    const service = await CityTaxi.findByIdAndDelete(id);
    if (!service) {
        throw { message: 'City taxi service not found', statusCode: 404 };
    }
    return service;
};

// ==========================================
// ADMIN UTILITIES
// ==========================================

exports.getAdminOverview = async () => {
    const [intercityCount, airportCount, cityCount] = await Promise.all([
        IntercityRoute.countDocuments(),
        AirportRoute.countDocuments(),
        CityTaxi.countDocuments()
    ]);

    return {
        intercityRoutes: intercityCount,
        airportRoutes: airportCount,
        cityTaxiServices: cityCount,
        total: intercityCount + airportCount + cityCount
    };
};

exports.toggleActiveStatus = async (type, id) => {
    let Model;
    switch (type) {
        case 'intercity':
            Model = IntercityRoute;
            break;
        case 'airport':
            Model = AirportRoute;
            break;
        case 'city':
            Model = CityTaxi;
            break;
        default:
            throw { message: 'Invalid type', statusCode: 400 };
    }

    const entity = await Model.findById(id);
    if (!entity) {
        throw { message: 'Entity not found', statusCode: 404 };
    }

    entity.isActive = !entity.isActive;
    await entity.save();
    return entity;
};

exports.searchIntercityCabs = async (slug, queryParams = {}) => {
    console.log('🔍 searchIntercityCabs called with slug:', slug);

    const route = await IntercityRoute.findOne({ slug: { $regex: new RegExp(`^${slug}$`, 'i') }, isActive: true }).lean();

    console.log('📍 Route found:', route ? 'YES' : 'NO');
    if (route) {
        console.log('   route.slug:', route.slug);
        console.log('   route.originCoordinates:', route.originCoordinates);
        console.log('   route.destinationCoordinates:', route.destinationCoordinates);
    }

    if (!route) throw { message: 'Intercity route not found', statusCode: 404 };

    // Validate coordinates exist
    const hasOriginCoords = route.originCoordinates && route.originCoordinates.coordinates && route.originCoordinates.coordinates.length === 2;
    const hasDestCoords = route.destinationCoordinates && route.destinationCoordinates.coordinates && route.destinationCoordinates.coordinates.length === 2;

    console.log('   hasOriginCoords:', hasOriginCoords);
    console.log('   hasDestCoords:', hasDestCoords);

    if (!hasOriginCoords || !hasDestCoords) {
        console.log('❌ Coordinates validation FAILED');
        throw {
            message: 'Route coordinates not configured. Please run: node src/seeds/update-coordinates.js',
            statusCode: 400
        };
    }

    console.log('✅ Coordinates validation PASSED');

    // Get tripType from query params - 'roundTrip' for round trip, 'oneWay' for one way
    const tripType = queryParams.tripType === 'roundTrip' ? 'roundTrip' : 'oneWay';

    // For round trip, double the distance for pricing calculation
    const effectiveDistance = tripType === 'roundTrip' ? route.distance * 2 : route.distance;

    console.log('🚗 Trip type:', tripType, '| Base distance:', route.distance, 'km | Effective distance:', effectiveDistance, 'km');

    const searchParams = {
        page: queryParams.page || 1,
        limit: queryParams.limit || 10,
        fuelType: queryParams.fuelType,
        isAc: queryParams.isAc === 'true' || queryParams.isAc === true,
        startTime: queryParams.startTime || new Date().toISOString(),
        sourceLat: route.originCoordinates.coordinates[1],
        sourceLong: route.originCoordinates.coordinates[0],
        destLat: route.destinationCoordinates.coordinates[1],
        destLong: route.destinationCoordinates.coordinates[0],
        tripType: tripType,
        zoneId: route.zone,
        distance: effectiveDistance,
        parsedStops: []
    };

    return await bookingService.searchAvailableCabs(searchParams, {
        page: searchParams.page,
        limit: searchParams.limit
    });
};

exports.searchAirportCabs = async (slug, queryParams = {}) => {
    const route = await AirportRoute.findOne({
        slug: { $regex: new RegExp(`^${slug}$`, 'i') },
        isActive: true
    }).lean();

    if (!route) throw { message: 'Airport route not found', statusCode: 404 };

    // Validate coordinates exist; if not, try to auto-heal
    let hasCoords = route.coordinates && route.coordinates.coordinates && route.coordinates.coordinates.length === 2;
    let cityCoordsValid = route.cityCoordinates && route.cityCoordinates.coordinates && route.cityCoordinates.coordinates.length === 2;

    // Check if coordinates look suspicious (e.g. distance > 500km used as proxy for bad location, like "Nottingham, UK" for "Bangalore")
    let suspiciousCoordinates = false;
    if (hasCoords && cityCoordsValid) {
        const dist = bookingService.calculateDistance(
            route.coordinates.coordinates[1], route.coordinates.coordinates[0],
            route.cityCoordinates.coordinates[1], route.cityCoordinates.coordinates[0]
        );
        if (dist > 500) { // Airport to City should not be > 500km
            console.warn(`Suspicious coordinates detected for route ${slug}. Calculated distance: ${dist}km. Triggering auto-heal.`);
            suspiciousCoordinates = true;
        }
    }

    if (!hasCoords || !cityCoordsValid || suspiciousCoordinates) {
        console.log(`Auto-healing missing or suspicious coordinates for airport route: ${slug}`);
        try {
            // Auto-fetch coordinates
            await _enrichRouteData('airport', route);

            // Check again
            hasCoords = route.coordinates && route.coordinates.coordinates && route.coordinates.coordinates.length === 2;
            cityCoordsValid = route.cityCoordinates && route.cityCoordinates.coordinates && route.cityCoordinates.coordinates.length === 2;

            if (hasCoords) {
                // Persist the fix to database so next time it's fast
                await AirportRoute.findByIdAndUpdate(route._id, {
                    coordinates: route.coordinates,
                    cityCoordinates: route.cityCoordinates,
                    distance: route.distance,
                    duration: route.duration
                });
                console.log(`Successfully updated coordinates for route: ${slug}`);
            }
        } catch (err) {
            console.error('Error auto-healing coordinates:', err);
        }
    }

    // Validation moved to later step to allow dynamic coordinates

    // Validating coordinates and calculating parameters...


    // Determine Dynamic Coordinates
    const airportLat = route.coordinates?.coordinates?.[1] || 0;
    const airportLng = route.coordinates?.coordinates?.[0] || 0;

    // Default City Coordinates from Route (if available) or 0
    let cityLat = route.cityCoordinates?.coordinates ? route.cityCoordinates.coordinates[1] : 0;
    let cityLng = route.cityCoordinates?.coordinates ? route.cityCoordinates.coordinates[0] : 0;

    // Check if we have valid coordinates either from storage or query params
    const hasStoredCoords = airportLat !== 0 && airportLng !== 0;

    // We can proceed if we have stored coords OR if the user provided FULL dynamic coords
    const hasDynamicSource = queryParams.sourceLat && queryParams.sourceLong;
    const hasDynamicDest = queryParams.destLat && queryParams.destLong;
    const hasFullDynamicCoords = hasDynamicSource && hasDynamicDest;

    if (!hasStoredCoords && !hasFullDynamicCoords) {
        throw {
            message: 'Airport coordinates not configured and no dynamic location provided. Please run: node src/seeds/update-coordinates.js',
            statusCode: 400
        };
    }

    let sourceLat, sourceLong, destLat, destLong;

    if (route.routeType === 'from_airport') {
        // Source is Airport
        sourceLat = (queryParams.sourceLat && parseFloat(queryParams.sourceLat)) || airportLat;
        sourceLong = (queryParams.sourceLong && parseFloat(queryParams.sourceLong)) || airportLng;

        // Destination is City
        destLat = (queryParams.destLat && parseFloat(queryParams.destLat)) || cityLat;
        destLong = (queryParams.destLong && parseFloat(queryParams.destLong)) || cityLng;

    } else {
        // Source is City
        sourceLat = (queryParams.sourceLat && parseFloat(queryParams.sourceLat)) || cityLat;
        sourceLong = (queryParams.sourceLong && parseFloat(queryParams.sourceLong)) || cityLng;

        // Destination is Airport
        destLat = (queryParams.destLat && parseFloat(queryParams.destLat)) || airportLat;
        destLong = (queryParams.destLong && parseFloat(queryParams.destLong)) || airportLng;
    }

    // Calculate dynamic distance if coordinates differ from stored route coordinates
    let searchDistance = route.distance;
    const usingDynamicCoords = (
        (queryParams.sourceLat && queryParams.destLat) ||
        (queryParams.sourceLong && queryParams.destLong)
    );

    if (usingDynamicCoords && sourceLat && sourceLong && destLat && destLong) {
        if (sourceLat !== 0 && sourceLong !== 0 && destLat !== 0 && destLong !== 0) {
            // Check if coordinates differ significantly from stored route (more than 1km difference)
            const sourceMatchesStored = route.routeType === 'from_airport'
                ? (Math.abs(sourceLat - airportLat) < 0.01 && Math.abs(sourceLong - airportLng) < 0.01)
                : (Math.abs(sourceLat - cityLat) < 0.01 && Math.abs(sourceLong - cityLng) < 0.01);

            if (!sourceMatchesStored) {
                // User provided different coordinates - use Google Maps API for accurate distance
                try {
                    const gMapsResult = await mapService.getDistanceAndDuration(
                        { lat: sourceLat, lng: sourceLong },
                        { lat: destLat, lng: destLong }
                    );
                    if (gMapsResult.distance > 0) {
                        searchDistance = gMapsResult.distance;
                        console.log(`Airport Search: Using Google Maps distance for dynamic coords: ${searchDistance} km`);
                    }
                } catch (gMapsError) {
                    console.warn('Google Maps distance calculation failed, using Haversine fallback:', gMapsError.message);
                    // Fallback to Haversine with 1.3x road factor
                    const straightLineDistance = bookingService.calculateDistance(sourceLat, sourceLong, destLat, destLong);
                    searchDistance = Math.round(straightLineDistance * 1.3); // Apply road factor
                }
            } else {
                // Coordinates match stored route - use pre-calculated distance
                console.log(`Airport Search: Using stored route distance: ${route.distance} km`);
            }
        }
    }

    const searchParams = {
        page: queryParams.page || 1,
        limit: queryParams.limit || 10,
        fuelType: queryParams.fuelType,
        isAc: queryParams.isAc == 'true' || queryParams.isAc === true,
        startTime: queryParams.startTime || new Date().toISOString(),
        tripType: 'airport',
        zoneId: route.zone,
        distance: searchDistance,
        parsedStops: [],
        sourceLat,
        sourceLong,
        destLat,
        destLong
    };

    return await bookingService.searchAvailableCabs(searchParams, {
        page: searchParams.page,
        limit: searchParams.limit
    });
};

exports.searchCityCabs = async (slug, queryParams = {}) => {
    const route = await CityTaxi.findOne({
        slug: { $regex: new RegExp(`^${slug}$`, 'i') },
        isActive: true
    }).lean();

    if (!route) throw { message: 'City taxi service not found', statusCode: 404 };

    // Validate coordinates exist
    const hasCoords = route.coordinates && route.coordinates.coordinates && route.coordinates.coordinates.length === 2;
    if (!hasCoords) {
        throw {
            message: 'City coordinates not configured. Please run: node src/seeds/update-coordinates.js',
            statusCode: 400
        };
    }

    const searchParams = {
        page: queryParams.page || 1,
        limit: queryParams.limit || 10,
        fuelType: queryParams.fuelType,
        isAc: queryParams.isAc === 'true' || queryParams.isAc === true,
        startTime: queryParams.startTime || new Date().toISOString(),
        sourceLat: route.coordinates.coordinates[1],
        sourceLong: route.coordinates.coordinates[0],
        tripType: 'oneWay',
        zoneId: route.zone,
        parsedStops: []
    };

    return await bookingService.searchAvailableCabs(searchParams, {
        page: searchParams.page,
        limit: searchParams.limit
    });
};