<?php
/**
 * ICYLAB OS - Google Maps / Places helper.
 *
 * Usa Google Places/Geocoding sólo si GOOGLE_MAPS_API_KEY está configurada.
 * Soporta restricción dinámica por país. Si el país viene vacío/Otro, busca globalmente.
 */

require_once __DIR__ . '/../../core/location.php';

class GoogleMapsService
{
    private $apiKey;
    private $country;
    private $language;

    public function __construct($apiKey = null, $country = 'cl', $language = 'es')
    {
        if ($apiKey === null) {
            if (defined('GOOGLE_MAPS_API_KEY')) {
                $apiKey = GOOGLE_MAPS_API_KEY;
            } else {
                $apiKey = getenv('GOOGLE_MAPS_API_KEY') ?: '';
            }
        }

        $this->apiKey = trim((string)$apiKey);
        $this->country = $this->normalizeCountry($country);
        $this->language = strtolower(trim((string)$language ?: 'es'));
    }

    public function isConfigured()
    {
        return $this->apiKey !== '' && stripos($this->apiKey, 'TU_') !== 0;
    }

    public function autocomplete($input, $limit = 8)
    {
        $input = trim((string)$input);
        if (!$this->isConfigured() || mb_strlen($input) < 3) {
            return array();
        }

        $params = array(
            'input' => $input,
            'key' => $this->apiKey,
            'language' => $this->language,
            'types' => 'geocode'
        );

        if ($this->country !== '') {
            $params['components'] = 'country:' . $this->country;
        }

        $json = $this->getJson('https://maps.googleapis.com/maps/api/place/autocomplete/json', $params);
        if (!is_array($json) || ($json['status'] ?? '') !== 'OK') {
            return array();
        }

        $rows = array();
        foreach (($json['predictions'] ?? array()) as $prediction) {
            $rows[] = array(
                'place_id' => $prediction['place_id'] ?? '',
                'description' => $prediction['description'] ?? '',
                'main_text' => $prediction['structured_formatting']['main_text'] ?? ($prediction['description'] ?? ''),
                'secondary_text' => $prediction['structured_formatting']['secondary_text'] ?? ''
            );
            if (count($rows) >= $limit) break;
        }

        return $rows;
    }

    public function placeDetails($placeId)
    {
        $placeId = trim((string)$placeId);
        if (!$this->isConfigured() || $placeId === '') {
            return null;
        }

        $params = array(
            'place_id' => $placeId,
            'key' => $this->apiKey,
            'language' => $this->language,
            'fields' => 'place_id,name,formatted_address,address_components,geometry'
        );

        $json = $this->getJson('https://maps.googleapis.com/maps/api/place/details/json', $params);
        if (!is_array($json) || ($json['status'] ?? '') !== 'OK' || empty($json['result'])) {
            return null;
        }

        return $this->normalizePlace($json['result']);
    }

    public function geocode($query, $country = null)
    {
        $query = trim((string)$query);
        if (!$this->isConfigured() || $query === '') {
            return null;
        }

        $countryCode = $country === null ? $this->country : $this->normalizeCountry($country);

        $params = array(
            'address' => $query,
            'key' => $this->apiKey,
            'language' => $this->language
        );

        if ($countryCode !== '') {
            $params['components'] = 'country:' . $countryCode;
        }

        $json = $this->getJson('https://maps.googleapis.com/maps/api/geocode/json', $params);
        if (!is_array($json) || ($json['status'] ?? '') !== 'OK' || empty($json['results'][0])) {
            return null;
        }

        return $this->normalizePlace($json['results'][0]);
    }

    private function normalizeCountry($country)
    {
        $country = trim((string)$country);
        if ($country === '' || strtolower($country) === 'global' || strtolower($country) === 'other' || strtolower($country) === 'otro') {
            return '';
        }
        return icylab_country_code_from_value($country);
    }

    private function normalizePlace(array $place)
    {
        $components = $place['address_components'] ?? array();
        $streetNumber = $this->component($components, 'street_number');
        $route = $this->component($components, 'route');

        $address = trim($route . ($streetNumber !== '' ? ' ' . $streetNumber : ''));
        if ($address === '') {
            $address = $place['formatted_address'] ?? '';
        }

        $district = $this->component($components, 'administrative_area_level_3');
        if ($district === '') $district = $this->component($components, 'locality');
        if ($district === '') $district = $this->component($components, 'sublocality');
        if ($district === '') $district = $this->component($components, 'administrative_area_level_2');

        $city = $this->component($components, 'locality');
        if ($city === '') $city = $this->component($components, 'administrative_area_level_2');
        if ($city === '') $city = $district;

        $region = $this->component($components, 'administrative_area_level_1');
        $country = $this->component($components, 'country');
        $location = $place['geometry']['location'] ?? array();

        return array(
            'place_id' => $place['place_id'] ?? '',
            'name' => $place['name'] ?? '',
            'formatted_address' => $place['formatted_address'] ?? '',
            'address' => $address,
            'district' => $district,
            'city' => $city,
            'region' => $region,
            'country' => $country ?: icylab_country_name_from_code($this->country),
            'latitude' => isset($location['lat']) ? (float)$location['lat'] : null,
            'longitude' => isset($location['lng']) ? (float)$location['lng'] : null,
            'geocode_status' => 'ok',
            'geocode_source' => 'google_maps',
            'geocode_query' => $place['formatted_address'] ?? ($place['name'] ?? '')
        );
    }

    private function component(array $components, $type)
    {
        foreach ($components as $component) {
            if (in_array($type, $component['types'] ?? array(), true)) {
                return trim((string)($component['long_name'] ?? ''));
            }
        }
        return '';
    }

    private function getJson($baseUrl, array $params)
    {
        $url = $baseUrl . '?' . http_build_query($params);
        $context = stream_context_create(array(
            'http' => array(
                'timeout' => 8,
                'ignore_errors' => true,
                'header' => "Accept: application/json
"
            )
        ));

        $raw = @file_get_contents($url, false, $context);
        if ($raw === false || $raw === '') {
            return null;
        }

        $json = json_decode($raw, true);
        return is_array($json) ? $json : null;
    }
}
