<?php

// validate_address.php
// Implementiert eine Geocoding-Strategie mit Nominatim als primärer Quelle 
// (strukturiert) und HERE als Fallback (Freitext).
// AKTUALISIERT: Match-Ausdrücke und Union Types durch PHP 7-kompatible
// Syntax (switch-Statements, kein striktes Typing) ersetzt, um 500er Fehler zu vermeiden.

// ini_set('display_errors', 1);
error_reporting(E_ALL);

// ***************************************************************
// LÖSUNG DES CORS-FEHLERS
// ***************************************************************
header('Access-Control-Allow-Origin: *');

// Laden der Logging-Funktionen
$debugLogFile = __DIR__ . '/validate_address_details_debug.log';
// require_once __DIR__ . '/logging_functions.php';

// Sicherstellen, dass der Content-Type als JSON mit UTF-8 gesendet wird
header('Content-Type: application/json; charset=utf-8');

// Funktion für internes Debug-Logging (falls logging_functions.php fehlt)
if (!function_exists('internal_debug_log')) {
    function internal_debug_log(string $message, string $logFile) {
        // Fügt den Fehler in das allgemeine PHP Error Log hinzu
        error_log(date('[d.m.Y, H:i:s] ') . $message); 
    }
}

internal_debug_log("DEBUG: validate_address.php gestartet (PHP 7 kompatibel).", $debugLogFile);

// Ihr HERE API Schlüssel (wird nur im Fallback benötigt)
$here_api_key = 'okEOI_7ww-l-Eop_6L8XY8YpWT2G-3bBNcO7ZoVT_P8';

/**
 * Führt einen cURL-Aufruf aus und gibt die Rohantwort zurück.
 * (Rückgabetypdeklaration entfernt für PHP 7 Kompatibilität)
 * @param string $url
 * @param array $headers
 * @return string|bool Die rohe Antwort oder false im Fehlerfall.
 */
function perform_curl_request(string $url, array $headers = [])
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
    curl_setopt(CURLOPT_HTTPHEADER, array_merge($headers, [
        'User-Agent: Stolperclean/1.0 (Stolperclean@gmail.com)'
    ]));

    $response = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error_msg = curl_error($ch);
    
    curl_close($ch);

    if ($response === false || $http_code >= 400 || curl_errno($ch)) {
        error_log("ERROR: cURL-Fehler oder HTTP Error {$http_code} bei URL {$url}: {$error_msg}");
        return false;
    }
    
    return $response;
}

/**
 * Geokodierung primär über Nominatim (OpenStreetMap) mit STRUKTURIERTER ABFRAGE.
 */
function geocodeNominatim(string $street_no, string $city, string $country, string $debugLogFile): ?array 
{
    // ... Nominatim Logik unverändert ...
    $url = "https://nominatim.openstreetmap.org/search?" . 
           "street=" . urlencode($street_no) . 
           "&city=" . urlencode($city) . 
           "&country=" . urlencode($country) . 
           "&format=json&limit=1&addressdetails=1";
    
    internal_debug_log("DEBUG: Versuch 1 (Nominatim strukturiert) URL: " . $url, $debugLogFile);

    $response = perform_curl_request($url);

    if ($response === false) {
        internal_debug_log("WARN: Nominatim cURL Fehler oder HTTP Error.", $debugLogFile);
        return null;
    }

    $data = json_decode($response, true);

    if (json_last_error() !== JSON_ERROR_NONE || empty($data) || !is_array($data)) {
        internal_debug_log("WARN: Nominatim-Antwort ungültig oder leer.", $debugLogFile);
        return null; 
    }
    
    $bestItem = $data[0] ?? null;

    if ($bestItem) {
        if (($bestItem['address']['country_code'] ?? '') !== 'de') {
             internal_debug_log("WARN: Nominatim-Treffer nicht in Deutschland gefunden.", $debugLogFile);
             return null;
        }

        $resultType = 'address'; 
        $houseNumberType = null;
        
        if (isset($bestItem['address']['house_number']) && !empty($bestItem['address']['house_number'])) {
            $resultType = 'pointAddress';
            $houseNumberType = 'PA'; 
        } 
        else if (in_array($bestItem['type'] ?? '', ['road', 'footway', 'street']) || 
                 (isset($bestItem['address']['road']) && !isset($bestItem['address']['house_number']))) {
            $resultType = 'street';
        }
        else if (in_array($bestItem['type'] ?? '', ['city', 'town', 'village', 'locality'])) {
            $resultType = 'city';
        }

        internal_debug_log("DEBUG: Nominatim erfolgreich gefunden. Typ: {$resultType}", $debugLogFile);

        return [
            "lat" => (float)$bestItem['lat'],
            "lon" => (float)$bestItem['lon'],
            "source" => "Nominatim",
            "city" => $bestItem['address']['city'] ?? $bestItem['address']['town'] ?? $bestItem['address']['village'] ?? 'Unbekannt',
            "resultType" => $resultType,
            "houseNumberType" => $houseNumberType
        ];
    }
    
    return null;
}

/**
 * Geokodierung Fallback über HERE (Freitext-Abfrage).
 */
function geocodeHere(string $query, string $here_api_key, string $debugLogFile): ?array
{
    $search_query = urlencode($query);
    $url = "https://geocode.search.hereapi.com/v1/geocode?q={$search_query}&apiKey={$here_api_key}&limit=5"; 
    
    internal_debug_log("DEBUG: Versuch 2 (HERE Fallback) URL: " . $url, $debugLogFile);

    $response = perform_curl_request($url);

    if ($response === false) {
        internal_debug_log("ERROR: HERE cURL Fehler oder HTTP Error.", $debugLogFile);
        return null;
    }

    $here_data = json_decode($response, true);
    
    if (json_last_error() !== JSON_ERROR_NONE || !is_array($here_data)) {
        internal_debug_log("ERROR: HERE-Antwort ungültig oder leer.", $debugLogFile);
        return null;
    }
    
    $best_berlin_item = null;

    if (isset($here_data['items']) && is_array($here_data['items'])) {
        foreach ($here_data['items'] as $item) {
            $city = $item['address']['city'] ?? '';
            
            if ($city === 'Berlin') {
                $best_berlin_item = $item;
                break; 
            }
        }
    }
    
    if ($best_berlin_item) {
        internal_debug_log("DEBUG: HERE Fallback erfolgreich (nach Berlin-Filter).", $debugLogFile);
        
        $hereResultType = $best_berlin_item['resultType'] ?? 'address';

        // PHP 7 kompatible switch-Anweisung ersetzt den match-Ausdruck
        $mappedResultType = 'address';
        switch ($hereResultType) {
            case 'houseNumber':
                $mappedResultType = 'pointAddress';
                break;
            case 'street':
                $mappedResultType = 'street';
                break;
            case 'locality':
                $mappedResultType = 'city';
                break;
        }
        
        return [
            "lat" => $best_berlin_item['position']['lat'],
            "lon" => $best_berlin_item['position']['lng'],
            "source" => "HERE",
            "city" => "Berlin",
            "resultType" => $mappedResultType,
            "houseNumberType" => $best_berlin_item['houseNumberType'] ?? null,
        ];
    }
    
    internal_debug_log("WARN: HERE Fallback fand keine Treffer in Berlin.", $debugLogFile);
    return null;
}


// ====================================================================
// HAUPTPROGRAMM
// ====================================================================

$street = trim($_GET['street'] ?? '');
$house_no = trim($_GET['house_no'] ?? '');
$city = trim($_GET['city'] ?? '');
$country = trim($_GET['country'] ?? ''); 

$street_no = trim("{$street} {$house_no}"); 

$combined_query_parts = array_filter([$street_no, $city, $country]);
$combined_query = implode(', ', $combined_query_parts);


if (!empty($street_no) && !empty($city) && !empty($country)) {
    
    internal_debug_log("DEBUG: Starte Suche mit strukturierter Nominatim-Abfrage.", $debugLogFile);
    
    // 1. VERSUCH: NOMINATIM (Strukturierte Abfrage)
    $result = geocodeNominatim($street_no, $city, $country, $debugLogFile);

    if (!$result) {
        // 2. VERSUCH: HERE FALLBACK (Freitext-Abfrage)
        internal_debug_log("DEBUG: Nominatim gescheitert. Versuche HERE-Fallback mit kombinierter Abfrage: '{$combined_query}'...", $debugLogFile);
        $result = geocodeHere($combined_query, $here_api_key, $debugLogFile);
    }
    
    if ($result) {
        // Erfolgreiche Antwort im standardisierten Format
        $final_response = [
            "items" => [
                [
                    "position" => ["lat" => $result['lat'], "lng" => $result['lon']],
                    "source" => $result['source'],
                    "city" => $result['city'],
                    "resultType" => $result['resultType'],
                    "houseNumberType" => $result['houseNumberType'] ?? null 
                ]
            ]
        ];
        echo json_encode($final_response);
    } else {
        internal_debug_log("WARN: Beide Geocoding-Dienste lieferten kein Ergebnis.", $debugLogFile);
        http_response_code(404);
        echo json_encode(['error' => 'Adresse nicht gefunden oder keine eindeutige Koordinate bestimmbar.']);
    }

} else {
    internal_debug_log("DEBUG: Es fehlen wesentliche Adressparameter (street/house_no, city, country) für die Geocodierung.", $debugLogFile);
    http_response_code(400);
    echo json_encode(['error' => 'Es fehlen wesentliche Adressparameter für die Geocodierung (street/house_no, city, country).']);
}

internal_debug_log("DEBUG: validate_address.php beendet.", $debugLogFile);
?>