const nocodbService = require('../services/nocodb');
const logger = require('../utils/logger');
const config = require('../config');
const { 
    syncGeoFields, 
    validateCoordinates, 
    checkBounds,
    extractId 
} = require('../utils/helpers');

class LocationsController {
    async getAll(req, res) {
        try {
            const { limit = 1000, offset = 0, where } = req.query;
            
            const params = { limit, offset };
            if (where) params.where = where;
            
            logger.info('Fetching locations from NocoDB');
            
            const response = await nocodbService.getLocations(params);
            const locations = response.list || [];
            
            // Process and validate locations
            const validLocations = locations.filter(loc => {
                loc = syncGeoFields(loc);
                
                if (loc.latitude && loc.longitude) {
                    return true;
                }
                
                // Try to parse from geodata column
                if (loc.geodata && typeof loc.geodata === 'string') {
                    const parts = loc.geodata.split(';');
                    if (parts.length === 2) {
                        loc.latitude = parseFloat(parts[0]);
                        loc.longitude = parseFloat(parts[1]);
                        return !isNaN(loc.latitude) && !isNaN(loc.longitude);
                    }
                }
                
                return false;
            });
            
            logger.info(`Retrieved ${validLocations.length} valid locations out of ${locations.length} total`);
            
            res.json({
                success: true,
                count: validLocations.length,
                total: response.pageInfo?.totalRows || validLocations.length,
                locations: validLocations
            });
            
        } catch (error) {
            logger.error('Error fetching locations:', error.message);
            
            if (error.response) {
                res.status(error.response.status).json({
                    success: false,
                    error: 'Failed to fetch data from NocoDB',
                    details: error.response.data
                });
            } else if (error.code === 'ECONNABORTED') {
                res.status(504).json({
                    success: false,
                    error: 'Request timeout'
                });
            } else {
                res.status(500).json({
                    success: false,
                    error: 'Internal server error'
                });
            }
        }
    }
    
    async getById(req, res) {
        try {
            const location = await nocodbService.getById(
                config.nocodb.tableId,
                req.params.id
            );
            
            res.json({
                success: true,
                location
            });
            
        } catch (error) {
            logger.error(`Error fetching location ${req.params.id}:`, error.message);
            res.status(error.response?.status || 500).json({
                success: false,
                error: 'Failed to fetch location'
            });
        }
    }
    
    async create(req, res) {
        try {
            let locationData = { ...req.body };
            locationData = syncGeoFields(locationData);
            
            const { latitude, longitude, ...additionalData } = locationData;
            
            // Validate coordinates
            const validation = validateCoordinates(latitude, longitude);
            if (!validation.valid) {
                return res.status(400).json({
                    success: false,
                    error: validation.error
                });
            }
            
            // Check bounds if configured
            if (config.map.bounds) {
                if (!checkBounds(validation.latitude, validation.longitude, config.map.bounds)) {
                    return res.status(400).json({
                        success: false,
                        error: 'Location is outside allowed bounds'
                    });
                }
            }
            
            // Format geodata with string values to preserve precision
            const geodata = `${validation.latitude};${validation.longitude}`;
            
            // Prepare data for NocoDB - keep coordinates as strings
            const finalData = {
                geodata,
                'Geo-Location': geodata,
                latitude: validation.latitude,
                longitude: validation.longitude,
                ...additionalData,
                created_at: new Date().toISOString(),
                created_by: req.session.userEmail
            };
            
            logger.info('Creating new location:', { 
                lat: validation.latitude, 
                lng: validation.longitude 
            });
            
            const response = await nocodbService.create(
                config.nocodb.tableId,
                finalData
            );
            
            logger.info('Location created successfully:', extractId(response));
            
            res.status(201).json({
                success: true,
                location: response
            });
            
        } catch (error) {
            logger.error('Error creating location:', error.message);
            
            if (error.response) {
                res.status(error.response.status).json({
                    success: false,
                    error: 'Failed to save location to NocoDB',
                    details: error.response.data
                });
            } else {
                res.status(500).json({
                    success: false,
                    error: 'Internal server error'
                });
            }
        }
    }
    
    async update(req, res) {
        try {
            const locationId = req.params.id;
            
            // Validate ID
            if (!locationId || locationId === 'undefined' || locationId === 'null') {
                return res.status(400).json({
                    success: false,
                    error: 'Invalid location ID'
                });
            }
            
            let updateData = { ...req.body };
            
            // Remove ID fields to avoid conflicts
            delete updateData.ID;
            delete updateData.Id;
            delete updateData.id;
            delete updateData._id;
            
            // Sync geo fields
            updateData = syncGeoFields(updateData);
            
            updateData.last_updated_at = new Date().toISOString();
            updateData.last_updated_by = req.session.userEmail;
            
            logger.info(`Updating location ${locationId} by ${req.session.userEmail}`);
            
            const response = await nocodbService.update(
                config.nocodb.tableId,
                locationId,
                updateData
            );
            
            res.json({
                success: true,
                location: response
            });
            
        } catch (error) {
            logger.error(`Error updating location ${req.params.id}:`, error.message);
            
            res.status(error.response?.status || 500).json({
                success: false,
                error: 'Failed to update location',
                details: error.response?.data?.message || error.message
            });
        }
    }
    
    async delete(req, res) {
        try {
            const locationId = req.params.id;
            
            // Validate ID
            if (!locationId || locationId === 'undefined' || locationId === 'null') {
                return res.status(400).json({
                    success: false,
                    error: 'Invalid location ID'
                });
            }
            
            await nocodbService.delete(
                config.nocodb.tableId,
                locationId
            );
            
            logger.info(`Location ${locationId} deleted by ${req.session.userEmail}`);
            
            res.json({
                success: true,
                message: 'Location deleted successfully'
            });
            
        } catch (error) {
            logger.error(`Error deleting location ${req.params.id}:`, error.message);
            res.status(error.response?.status || 500).json({
                success: false,
                error: 'Failed to delete location'
            });
        }
    }
}

module.exports = new LocationsController();