<?php
// fetch_poi_by_name.php
// Sucht Stolpersteine anhand von Namens- und Geburtsjahr-Ähnlichkeit.
// Extrahiert Geometrie-Koordinaten aus der PostGIS-Spalte geom_geolocation.
// Erwartet im POST-Body: { "name_parts": ["Max", "Emil", "Mustermann"], "year_of_birth": 1900 }

// PHP-Fehlermeldungen direkt anzeigen, nur für Debug-Zwecke
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// === Logging und Konfiguration laden ===
$debugLogFile = __DIR__ . '/fetch_poi_by_name_debug.log';

require_once __DIR__ . '/logging_functions.php'; 
require_once __DIR__ . '/fetch_poi_select.php';

internal_debug_log("--- " . basename(__FILE__) . " START (Request Methode: " . ($_SERVER['REQUEST_METHOD'] ?? 'UNKNOWN') . ") ---", $debugLogFile);
header('Content-Type: application/json');

// --- Gesamten Skriptinhalt in einen Try-Catch-Block einschließen ---
try {
    // --- Konfiguration laden ---
    $config = require_once 'config.php';
    
    // Variablen initialisieren
    $targetTable = ''; 
    $tableSuffix = '';

    // ------------------------------------------------------------------
    // === DATENQUELLEN-AUSWAHL MIT SICHERER WHITELISTING (p-Parameter) ===
    // ------------------------------------------------------------------

    $pParam = $_GET['p'] ?? 'default';

    switch ($pParam) {
        case 'default':
            $tableSuffix = '';
            break;
        case 'test':
            $tableSuffix = '_test';
            break;
        default:
            // Falls ein ungültiger Wert übergeben wird, Standard verwenden.
            $tableSuffix = '';
            $pParam = 'default';
            break;
    }

    // Berechnet den finalen Tabellennamen
    $targetTable = $config['tablePrefix'] . $tableSuffix;

    internal_debug_log("Datenquelle: p=$pParam. Wird Tabelle '$targetTable' verwenden.", $debugLogFile);

    // Datenbankverbindungskonfiguration laden
    $dbConfig = require_once 'db-connection.php';
    internal_debug_log("DB config loaded.", $debugLogFile);

    $host = $dbConfig['host'] ?? 'localhost';
    $port = $dbConfig['port'] ?? 5432;
    $dbname = $dbConfig['dbname'] ?? '';
    $user = $dbConfig['user'] ?? '';
    $password = $dbConfig['password'] ?? '';

    // === Eingabedaten aus dem JSON-Body lesen ===
    if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
        throw new Exception('Falsche Request-Methode. Es wird POST erwartet.');
    }

    $input = file_get_contents('php://input');
    $data = json_decode($input, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        internal_debug_log("JSON Decode Error: " . json_last_error_msg() . ". Input war: " . substr($input, 0, 100), $debugLogFile);
        throw new Exception('Ungültige JSON-Eingabe.');
    }

    // === Validierung der Eingabedaten ===
    
    // 1. Name Parts extrahieren
    $nameParts = $data['name_parts'] ?? [];
    $namePartsCount = is_array($nameParts) ? count($nameParts) : 0;
    
    // 2. Geburtsjahr validieren (bleibt NULL, wenn ungültig oder fehlend)
    $yearOfBirthInput = $data['year_of_birth'] ?? null;
    $yearOfBirth = ($yearOfBirthInput && is_numeric($yearOfBirthInput) && (int)$yearOfBirthInput >= 1850 && (int)$yearOfBirthInput <= 2024) 
                   ? (int)$yearOfBirthInput 
                   : null;
    
    // 3. Kombinierte Validierungslogik 
    if ($namePartsCount === 0) {
        internal_debug_log("Fehlende Namensbestandteile.", $debugLogFile);
        throw new Exception('Fehlende Namensbestandteile.');
    }

    // Erlaubt: (>= 2 Teile) ODER (1 Teil UND gültiges Geburtsjahr)
    $isSearchValid = ($namePartsCount >= 2) || ($namePartsCount === 1 && $yearOfBirth !== null);
    
    if (!$isSearchValid) {
        $singleNamePart = $namePartsCount === 1 ? $nameParts[0] : 'kein Name gefunden';
        internal_debug_log("Ungültige Suche: Nur ein Namensbestandteil ($singleNamePart) gefunden, aber kein gültiges Geburtsjahr (1850-2024).", $debugLogFile);
        throw new Exception('Ungültige Suche: Es werden mindestens zwei Namensbestandteile oder ein Namensbestandteil und ein gültiges Geburtsjahr (1850-2024) benötigt.');
    }
    
    // === Vorverarbeitung für SQL-Ähnlichkeitssuche ===
    $searchName = implode('', $nameParts);
    $searchCombinedTarget = $searchName . ($yearOfBirth ? (string)$yearOfBirth : '');
    
    internal_debug_log("Suchparameter: Name='{$searchName}', Jahr=" . ($yearOfBirth ?? 'NULL') . ". Kombinierter Target: '{$searchCombinedTarget}'", $debugLogFile);

    // === Verbindung zur Datenbank herstellen ===
    $connString = "host=$host port=$port dbname=$dbname user=$user password=$password";
    $dbconn = @pg_connect($connString); 

    if (!$dbconn) {
        $dbError = pg_last_error();
        internal_debug_log("Database connection failed: " . $dbError, $debugLogFile);
        throw new Exception('Datenbankverbindung fehlgeschlagen');
    }
    internal_debug_log("Database connection successful.", $debugLogFile);

    pg_set_client_encoding($dbconn, "UTF8");

    // === SQL-Query vorbereiten und ausführen ===

    $similarityThreshold = 0.4; //0.4
    $params = [$searchCombinedTarget];
    
    // DYNAMISCHE WHERE-KLAUSEL:
    if ($namePartsCount === 1 && $yearOfBirth !== null) {
        $similarityThreshold = 0.7; //0.7
        // SPEZIALFALL: 1 Name + Jahr (z.B. "max 1892" oder "heidemann 1892").
        // Es wird gegen Vorname/Nachname + Jahr geprüft.
        $whereClause = "
            (
                similarity(
                    concat(first_name, CAST(year_of_birth AS TEXT)), 
                    CAST(\$1 AS TEXT)
                ) > {$similarityThreshold}
                OR 
                similarity(
                    concat(last_name, CAST(year_of_birth AS TEXT)), 
                    CAST(\$1 AS TEXT)
                ) > {$similarityThreshold}
            )
        ";
        // Sortiert nach der besten Übereinstimmung (Vorname ODER Nachname)
        $orderByExpression = "
            GREATEST(
                similarity(concat(first_name, CAST(year_of_birth AS TEXT)), CAST(\$1 AS TEXT)),
                similarity(concat(last_name, CAST(year_of_birth AS TEXT)), CAST(\$1 AS TEXT))
            ) DESC
        ";
        
    } else {
        // STANDARDFALL: >= 2 Namen (mit oder ohne Jahr)
        $dbCombinedTarget = "concat(first_name, last_name" . ($yearOfBirth ? ", CAST(year_of_birth AS TEXT)" : "") . ")";
        
        $whereClause = "
            similarity(
                {$dbCombinedTarget}, 
                CAST(\$1 AS TEXT)
            ) > {$similarityThreshold}
        ";
        $orderByExpression = "similarity({$dbCombinedTarget}, CAST(\$1 AS TEXT)) DESC"; // Sortiert nach der Hauptbedingung
    }

    // ANPASSUNG: Extrahieren der Koordinaten (lon, lat) aus geom_geolocation (PostGIS-Spalte)
    $poiColumns = getPoiSelectFields();
    $query = "
        SELECT 
            $poiColumns,    
            ST_X(geom_geolocation) AS lon,
            ST_Y(geom_geolocation) AS lat
        FROM public.\"{$targetTable}\" 
        WHERE 
            {$whereClause}
        ORDER BY
            {$orderByExpression}
    ";
    
    internal_debug_log("Executing SQL: " . $query . " with params: " . print_r($params, true), $debugLogFile);

    $result = pg_query_params($dbconn, $query, $params);

    if (!$result) {
        $dbError = pg_last_error($dbconn);
        internal_debug_log("SQL query failed: " . $dbError, $debugLogFile);
        throw new Exception('Datenbankabfrage fehlgeschlagen: ' . $dbError);
    }
    $rows = pg_fetch_all($result) ?: [];
    pg_free_result($result);

    internal_debug_log("Abfrage ausgeführt. Gefundene Datensätze: " . (count($rows) ?: 0), $debugLogFile);

    // === Ergebnis transformieren und zurückgeben ===
    $transformedRows = array_map(function($row) {
        // lat und lon werden jetzt aus der SQL-Abfrage als Aliase (lon, lat) zurückgegeben
        return [
            'source'     => 'POI',
            'precision'  => 'precise',
            'street'     => $row['street'] ?? '',
            'houseNr'    => $row['house_no'] ?? '', 
            'district'   => $row['localdistrict'] ?? '',
            'city'       => 'Berlin', 
            'postcode'   => '',
            'lat' => (float)($row['lat'] ?? 0),
            'lon' => (float)($row['lon'] ?? 0),
            
            'first_name'   => $row['first_name'] ?? '',
            'last_name'    => $row['last_name'] ?? '',
            'year_of_birth' => (int)($row['year_of_birth'] ?? 0),
            
            'display_name' => "Stolperstein: {$row['first_name']} {$row['last_name']} (geb. {$row['year_of_birth']})",
            'original_poi' => $row,
        ];
    }, $rows ?: []); 

    pg_close($dbconn);

    $response = [
        'success' => true,
        'data' => $transformedRows
    ];

    echo json_encode($response, JSON_PRETTY_PRINT);

} catch (Exception $e) {
    internal_debug_log("Caught global Exception: " . $e->getMessage(), $debugLogFile);
    // Setzt den Status-Code auf 400 für ungültige Benutzereingaben oder 500 für allgemeine Fehler.
    $statusCode = (strpos($e->getMessage(), 'Ungültige Suche:') !== false || strpos($e->getMessage(), 'Fehlende Namensbestandteile') !== false) ? 400 : 500;
    http_response_code($statusCode);
    echo json_encode(['success' => false, 'error' => 'Ein Serverfehler ist aufgetreten.', 'details' => $e->getMessage()], JSON_PRETTY_PRINT);
    
    if (isset($dbconn) && is_resource($dbconn)) {
        pg_close($dbconn);
    }
}

internal_debug_log("--- " . basename(__FILE__) . " END ---", $debugLogFile);
?>