/**
 * Update Coordinates Script
 * 
 * This script updates missing coordinates for SEO routes
 * Fixes the "Cannot read properties of undefined (reading 'coordinates')" error
 */

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 mapService = require('../services/map.service');

// Connect to database
async function connectDB() {
    try {
        const mongoUri = process.env.MONGO_URI || 'mongodb://localhost:27017/cab_booking';
        await mongoose.connect(mongoUri);
        console.log('✅ Connected to MongoDB');
    } catch (error) {
        console.error('❌ MongoDB connection failed:', error.message);
        process.exit(1);
    }
}

/**
 * Update coordinates for intercity routes
 */
async function updateIntercityRoutes() {
    console.log('\n🔄 Updating Intercity Routes...');
    
    try {
        const routes = await IntercityRoute.find({
            $or: [
                { originCoordinates: { $exists: false } },
                { destinationCoordinates: { $exists: false } },
                { 'originCoordinates.coordinates': { $size: 0 } },
                { 'destinationCoordinates.coordinates': { $size: 0 } }
            ]
        });

        console.log(`Found ${routes.length} intercity routes needing coordinate updates`);

        for (const route of routes) {
            console.log(`\n📍 Processing: ${route.originCity} to ${route.destinationCity}`);
            
            try {
                // Get coordinates for origin city
                if (!route.originCoordinates || !route.originCoordinates.coordinates || route.originCoordinates.coordinates.length === 0) {
                    console.log(`  🔍 Fetching coordinates for ${route.originCity}...`);
                    const originCoords = await mapService.getCoordinates(route.originCity);
                    
                    if (originCoords.lat !== 0 && originCoords.lng !== 0) {
                        route.originCoordinates = {
                            type: 'Point',
                            coordinates: [originCoords.lng, originCoords.lat]
                        };
                        console.log(`  ✅ Origin coordinates: ${originCoords.lat}, ${originCoords.lng}`);
                    } else {
                        console.log(`  ⚠️ Could not find coordinates for ${route.originCity}`);
                    }
                }

                // Get coordinates for destination city
                if (!route.destinationCoordinates || !route.destinationCoordinates.coordinates || route.destinationCoordinates.coordinates.length === 0) {
                    console.log(`  🔍 Fetching coordinates for ${route.destinationCity}...`);
                    const destCoords = await mapService.getCoordinates(route.destinationCity);
                    
                    if (destCoords.lat !== 0 && destCoords.lng !== 0) {
                        route.destinationCoordinates = {
                            type: 'Point',
                            coordinates: [destCoords.lng, destCoords.lat]
                        };
                        console.log(`  ✅ Destination coordinates: ${destCoords.lat}, ${destCoords.lng}`);
                    } else {
                        console.log(`  ⚠️ Could not find coordinates for ${route.destinationCity}`);
                    }
                }

                // Update distance and duration if not set or zero
                if ((!route.distance || route.distance === 0) && route.originCoordinates && route.destinationCoordinates) {
                    console.log(`  📏 Calculating distance and duration...`);
                    
                    try {
                        const stats = await mapService.getDistanceAndDuration(route.originCity, route.destinationCity);
                        if (stats.distance > 0) {
                            route.distance = stats.distance;
                            route.duration = stats.duration;
                            console.log(`  ✅ Distance: ${stats.distance} km, Duration: ${stats.duration} mins`);
                        }
                    } catch (distanceError) {
                        console.log(`  ⚠️ Could not calculate distance: ${distanceError.message}`);
                    }
                }

                // Save the updated route
                await route.save();
                console.log(`  💾 Route updated successfully`);
                
                // Add delay to avoid rate limiting
                await new Promise(resolve => setTimeout(resolve, 1000));
                
            } catch (error) {
                console.error(`  ❌ Error updating route ${route.originCity} to ${route.destinationCity}:`, error.message);
            }
        }

        console.log(`\n✅ Intercity routes update completed`);
        
    } catch (error) {
        console.error('❌ Error updating intercity routes:', error.message);
    }
}

/**
 * Update coordinates for airport routes
 */
async function updateAirportRoutes() {
    console.log('\n🔄 Updating Airport Routes...');
    
    try {
        const routes = await AirportRoute.find({
            $or: [
                { coordinates: { $exists: false } },
                { cityCoordinates: { $exists: false } },
                { 'coordinates.coordinates': { $size: 0 } },
                { 'cityCoordinates.coordinates': { $size: 0 } }
            ]
        });

        console.log(`Found ${routes.length} airport routes needing coordinate updates`);

        for (const route of routes) {
            console.log(`\n✈️ Processing: ${route.airportName} - ${route.cityName}`);
            
            try {
                // Get coordinates for airport
                if (!route.coordinates || !route.coordinates.coordinates || route.coordinates.coordinates.length === 0) {
                    console.log(`  🔍 Fetching coordinates for ${route.airportName}...`);
                    const airportQuery = route.airportName.toLowerCase().includes('india') ? route.airportName : `${route.airportName}, India`;
                    const airportCoords = await mapService.getCoordinates(airportQuery);
                    
                    if (airportCoords.lat !== 0 && airportCoords.lng !== 0) {
                        route.coordinates = {
                            type: 'Point',
                            coordinates: [airportCoords.lng, airportCoords.lat]
                        };
                        console.log(`  ✅ Airport coordinates: ${airportCoords.lat}, ${airportCoords.lng}`);
                    } else {
                        console.log(`  ⚠️ Could not find coordinates for ${route.airportName}`);
                    }
                }

                // Get coordinates for city
                if (!route.cityCoordinates || !route.cityCoordinates.coordinates || route.cityCoordinates.coordinates.length === 0) {
                    console.log(`  🔍 Fetching coordinates for ${route.cityName}...`);
                    const cityQuery = route.cityName.toLowerCase().includes('india') ? route.cityName : `${route.cityName}, India`;
                    const cityCoords = await mapService.getCoordinates(cityQuery);
                    
                    if (cityCoords.lat !== 0 && cityCoords.lng !== 0) {
                        route.cityCoordinates = {
                            type: 'Point',
                            coordinates: [cityCoords.lng, cityCoords.lat]
                        };
                        console.log(`  ✅ City coordinates: ${cityCoords.lat}, ${cityCoords.lng}`);
                    } else {
                        console.log(`  ⚠️ Could not find coordinates for ${route.cityName}`);
                    }
                }

                // Update distance and duration if not set or zero
                if ((!route.distance || route.distance === 0) && route.coordinates && route.cityCoordinates) {
                    console.log(`  📏 Calculating distance and duration...`);
                    
                    try {
                        const stats = await mapService.getDistanceAndDuration(route.airportName, route.cityName);
                        if (stats.distance > 0) {
                            route.distance = stats.distance;
                            route.duration = stats.duration;
                            console.log(`  ✅ Distance: ${stats.distance} km, Duration: ${stats.duration} mins`);
                        }
                    } catch (distanceError) {
                        console.log(`  ⚠️ Could not calculate distance: ${distanceError.message}`);
                    }
                }

                // Save the updated route
                await route.save();
                console.log(`  💾 Route updated successfully`);
                
                // Add delay to avoid rate limiting
                await new Promise(resolve => setTimeout(resolve, 1000));
                
            } catch (error) {
                console.error(`  ❌ Error updating route ${route.airportName} - ${route.cityName}:`, error.message);
            }
        }

        console.log(`\n✅ Airport routes update completed`);
        
    } catch (error) {
        console.error('❌ Error updating airport routes:', error.message);
    }
}

/**
 * Update coordinates for city taxi services
 */
async function updateCityTaxiServices() {
    console.log('\n🔄 Updating City Taxi Services...');
    
    try {
        const services = await CityTaxi.find({
            $or: [
                { coordinates: { $exists: false } },
                { 'coordinates.coordinates': { $size: 0 } }
            ]
        });

        console.log(`Found ${services.length} city taxi services needing coordinate updates`);

        for (const service of services) {
            console.log(`\n🏙️ Processing: ${service.cityName}`);
            
            try {
                // Get coordinates for city
                if (!service.coordinates || !service.coordinates.coordinates || service.coordinates.coordinates.length === 0) {
                    console.log(`  🔍 Fetching coordinates for ${service.cityName}...`);
                    const cityCoords = await mapService.getCoordinates(service.cityName);
                    
                    if (cityCoords.lat !== 0 && cityCoords.lng !== 0) {
                        service.coordinates = {
                            type: 'Point',
                            coordinates: [cityCoords.lng, cityCoords.lat]
                        };
                        console.log(`  ✅ City coordinates: ${cityCoords.lat}, ${cityCoords.lng}`);
                    } else {
                        console.log(`  ⚠️ Could not find coordinates for ${service.cityName}`);
                    }
                }

                // Save the updated service
                await service.save();
                console.log(`  💾 Service updated successfully`);
                
                // Add delay to avoid rate limiting
                await new Promise(resolve => setTimeout(resolve, 1000));
                
            } catch (error) {
                console.error(`  ❌ Error updating service ${service.cityName}:`, error.message);
            }
        }

        console.log(`\n✅ City taxi services update completed`);
        
    } catch (error) {
        console.error('❌ Error updating city taxi services:', error.message);
    }
}

/**
 * Main function
 */
async function main() {
    console.log('🚀 Starting coordinate update script...');
    console.log('This script will update missing coordinates for SEO routes');
    
    try {
        await connectDB();
        
        await updateIntercityRoutes();
        await updateAirportRoutes();
        await updateCityTaxiServices();
        
        console.log('\n🎉 All coordinate updates completed successfully!');
        console.log('\n📝 Summary:');
        console.log('- Intercity routes: Updated missing origin/destination coordinates');
        console.log('- Airport routes: Updated missing airport/city coordinates');
        console.log('- City taxi services: Updated missing city coordinates');
        console.log('\n✅ The "coordinates" error should now be resolved.');
        
    } catch (error) {
        console.error('❌ Script failed:', error.message);
        process.exit(1);
    } finally {
        await mongoose.disconnect();
        console.log('📡 Disconnected from MongoDB');
        process.exit(0);
    }
}

// Handle script termination
process.on('SIGINT', async () => {
    console.log('\n⏹️ Script interrupted by user');
    await mongoose.disconnect();
    process.exit(0);
});

process.on('unhandledRejection', async (error) => {
    console.error('❌ Unhandled rejection:', error.message);
    await mongoose.disconnect();
    process.exit(1);
});

// Run the script
if (require.main === module) {
    main();
}

module.exports = { main };