const socrataService = require('../services/socrata');
const logger = require('../utils/logger');

const EDMONTON_PARCEL_ADDRESSES_ID = 'nggt-rwac';

class ExternalDataController {
    /**
     * Fetches parcel addresses from the City of Edmonton open data portal.
     * Uses a simple SoQL query to get points with valid locations.
     */
    async getEdmontonParcelAddresses(req, res) {
        try {
            logger.info('Fetching Edmonton parcel addresses from Socrata API');
            
            // Get query parameters for filtering and pagination
            const { 
                bounds, 
                zoom = 10, 
                limit = 2000,
                offset = 0,
                neighborhood 
            } = req.query;
            
            // Build dynamic query based on zoom level and bounds
            let whereClause = 'location IS NOT NULL';
            let selectFields = 'house_number, street_name, sub_address, neighbourhood_name, object_type, location, latitude, longitude';
            
            // If bounds are provided, filter by geographic area
            if (bounds) {
                try {
                    const boundsArray = bounds.split(',').map(Number);
                    if (boundsArray.length === 4) {
                        const [south, west, north, east] = boundsArray;
                        whereClause += ` AND latitude BETWEEN ${south} AND ${north} AND longitude BETWEEN ${west} AND ${east}`;
                        logger.info(`Filtering by bounds: ${bounds}`);
                    }
                } catch (error) {
                    logger.warn('Invalid bounds parameter:', bounds);
                }
            }
            
            // Filter by neighborhood if specified
            if (neighborhood) {
                whereClause += ` AND neighbourhood_name = '${neighborhood.toUpperCase()}'`;
            }
            
            // Adjust limit based on zoom level - show fewer points when zoomed out
            const dynamicLimit = Math.min(parseInt(zoom) < 12 ? 500 : parseInt(zoom) < 15 ? 1500 : 2000, parseInt(limit));
            
            const params = {
                '$select': selectFields,
                '$where': whereClause,
                '$limit': dynamicLimit,
                '$offset': parseInt(offset),
                '$order': 'house_number'
            };

            const data = await socrataService.get(EDMONTON_PARCEL_ADDRESSES_ID, params);
            
            logger.info(`Successfully fetched ${data.length} Edmonton parcel addresses (zoom: ${zoom}, bounds: ${bounds})`);

            // Group addresses by location to identify multi-unit buildings
            const locationGroups = new Map();
            
            data.filter(item => item.location && item.location.coordinates).forEach(item => {
                const locationKey = `${item.latitude}_${item.longitude}`;
                const address = `${item.house_number || ''} ${item.street_name || ''}`.trim();
                
                if (!locationGroups.has(locationKey)) {
                    locationGroups.set(locationKey, {
                        address: address || 'No address',
                        location: item.location,
                        latitude: parseFloat(item.latitude),
                        longitude: parseFloat(item.longitude),
                        neighbourhood_name: item.neighbourhood_name || '',
                        suites: []
                    });
                }
                
                locationGroups.get(locationKey).suites.push({
                    suite: item.sub_address || item.suite || '',
                    object_type: item.object_type || 'SUITE',
                    record_id: item.record_id || '',
                    house_number: item.house_number || '',
                    street_name: item.street_name || ''
                });
            });

            // Transform grouped data into GeoJSON FeatureCollection
            const validFeatures = Array.from(locationGroups.values()).map(group => ({
                type: 'Feature',
                properties: {
                    address: group.address,
                    neighborhood: group.neighbourhood_name,
                    suites: group.suites,
                    suiteCount: group.suites.length,
                    isMultiUnit: group.suites.length > 3,
                    lat: group.latitude,
                    lng: group.longitude
                },
                geometry: group.location
            }));

            const geoJson = {
                type: 'FeatureCollection',
                features: validFeatures,
                metadata: {
                    count: validFeatures.length,
                    zoom: zoom,
                    bounds: bounds,
                    hasMore: validFeatures.length === dynamicLimit // Indicates if there might be more data
                }
            };

            logger.info(`Processed ${validFeatures.length} valid features`);

            res.json({
                success: true,
                data: geoJson
            });

        } catch (error) {
            logger.error('Error fetching Edmonton parcel addresses:', error);
            res.status(500).json({
                success: false,
                error: 'Failed to fetch external map data.'
            });
        }
    }
}

module.exports = new ExternalDataController();
