const geocoding = require('../services/geocoding'); const db = require('../models/db'); const logger = require('../utils/logger'); async function geocodeAddress(req, res) { try { const { address } = req.query; if (!address) { return res.status(400).json({ error: 'Address parameter required' }); } const result = await geocoding.forwardGeocode(address); res.json({ success: true, result: { latitude: result.latitude, longitude: result.longitude, formattedAddress: result.formattedAddress, provider: result.provider, confidence: result.confidence } }); } catch (error) { logger.error('Geocoding failed', { error: error.message }); res.status(500).json({ success: false, error: error.message }); } } async function reverseGeocode(req, res) { try { const { lat, lng } = req.query; if (!lat || !lng) { return res.status(400).json({ error: 'lat and lng parameters required' }); } const latitude = parseFloat(lat); const longitude = parseFloat(lng); if (isNaN(latitude) || isNaN(longitude)) { return res.status(400).json({ error: 'Invalid coordinates' }); } const result = await geocoding.reverseGeocode(latitude, longitude); res.json({ success: true, result: { formattedAddress: result.formattedAddress, components: result.components, latitude: result.latitude, longitude: result.longitude } }); } catch (error) { logger.error('Reverse geocoding failed', { error: error.message }); res.status(500).json({ success: false, error: error.message }); } } async function regeocodeResource(req, res) { try { const { id } = req.params; // Get the resource const resourceResult = await db.query( 'SELECT id, name, address, city, postal_code FROM food_resources WHERE id = $1', [id] ); if (resourceResult.rows.length === 0) { return res.status(404).json({ success: false, error: 'Resource not found' }); } const resource = resourceResult.rows[0]; // Build address string let addressToGeocode; let hasStreetAddress = false; if (resource.address && !resource.address.startsWith('PO Box') && resource.address.trim() !== '') { addressToGeocode = `${resource.address}, ${resource.city}, Alberta, Canada`; hasStreetAddress = true; } else if (resource.postal_code && resource.postal_code.trim() !== '') { addressToGeocode = `${resource.city}, ${resource.postal_code}, Alberta, Canada`; } else if (resource.city) { addressToGeocode = `${resource.city}, Alberta, Canada`; } else { return res.status(400).json({ success: false, error: 'Resource has no address or city to geocode' }); } logger.info(`Re-geocoding resource ${id}: ${resource.name}`, { address: addressToGeocode }); const geocodeResult = await geocoding.forwardGeocode(addressToGeocode); if (!geocodeResult || !geocodeResult.latitude || !geocodeResult.longitude) { return res.status(400).json({ success: false, error: 'Could not geocode address' }); } const confidence = geocodeResult.combinedConfidence || geocodeResult.confidence || 50; const provider = geocodeResult.provider || 'unknown'; const warnings = geocodeResult.validation?.warnings || []; // Adjust confidence if no street address was provided const adjustedConfidence = hasStreetAddress ? confidence : Math.min(confidence, 40); // Update the database await db.query(` UPDATE food_resources SET latitude = $1, longitude = $2, geocode_confidence = $3, geocode_provider = $4, updated_at = NOW() WHERE id = $5 `, [geocodeResult.latitude, geocodeResult.longitude, adjustedConfidence, provider, id]); logger.info(`Re-geocoded resource ${id} successfully`, { latitude: geocodeResult.latitude, longitude: geocodeResult.longitude, confidence: adjustedConfidence, provider }); res.json({ success: true, result: { latitude: geocodeResult.latitude, longitude: geocodeResult.longitude, confidence: adjustedConfidence, provider, warnings, formattedAddress: geocodeResult.formattedAddress } }); } catch (error) { logger.error('Re-geocoding failed', { error: error.message, id: req.params.id }); res.status(500).json({ success: false, error: error.message }); } } module.exports = { geocodeAddress, reverseGeocode, regeocodeResource };