<?php
/**
 * Wetter: Abruf und Cache (Geocoding + Open-Meteo Forecast).
 * Wird von api_wetter.php und cron_refresh_wetter.php genutzt.
 */

if (!defined('APP_ROOT')) {
    return;
}

require_once __DIR__ . '/functions_cache.php';

/** Cache-TTL in Sekunden (30 Minuten) */
const WETTER_CACHE_TTL = 1800;

/**
 * Wetter für Ort/PLZ laden. Liest aus Cache oder ruft APIs auf und schreibt Cache.
 * @param string $plz Ort oder PLZ (z.B. 97478 oder Knetzgau)
 * @return array ['ok' => bool, 'current' => [...], 'daily' => [...]] oder ['ok' => false, 'error' => string]
 */
function function_wetter_fetch(string $plz): array
{
    $plz = trim($plz);
    if ($plz === '') {
        return ['ok' => false, 'error' => 'Parameter plz fehlt'];
    }

    $cacheKey = md5(strtolower($plz));
    $mem = function_cache_get('wetter_' . $cacheKey);
    if ($mem !== null) {
        return $mem;
    }

    $cacheDir = STORAGE_ROOT . '/wetter_cache';
    $cacheFile = $cacheDir . '/' . $cacheKey . '.json';

    if (is_dir($cacheDir) && is_readable($cacheFile)) {
        $cached = @file_get_contents($cacheFile);
        if ($cached !== false) {
            $decoded = json_decode($cached, true);
            if (!empty($decoded['data']) && !empty($decoded['expires']) && (int) $decoded['expires'] > time()) {
                $data = $decoded['data'];
                function_cache_set('wetter_' . $cacheKey, $data);
                return $data;
            }
        }
    }

    $search = preg_match('/^\d{4,6}$/', $plz) ? $plz . ', Germany' : $plz . ', Germany';
    $lat = null;
    $lon = null;
    $tz = 'Europe/Berlin';

    $ctx = stream_context_create(['http' => ['timeout' => 8]]);

    $geoUrl = 'https://geocoding-api.open-meteo.com/v1/search?' . http_build_query([
        'name' => $search,
        'count' => 1,
        'language' => 'de',
        'format' => 'json'
    ]);
    $geoJson = @file_get_contents($geoUrl, false, $ctx);
    if ($geoJson !== false) {
        $geo = json_decode($geoJson, true);
        if (!empty($geo['results'][0])) {
            $lat = (float) $geo['results'][0]['latitude'];
            $lon = (float) $geo['results'][0]['longitude'];
            $tz = $geo['results'][0]['timezone'] ?? 'Europe/Berlin';
        }
    }

    if ($lat === null && $lon === null) {
        $nominatimUrl = 'https://nominatim.openstreetmap.org/search?' . http_build_query([
            'q' => $search,
            'format' => 'json',
            'limit' => 1
        ]);
        $ctxNom = stream_context_create([
            'http' => [
                'timeout' => 8,
                'header' => "User-Agent: Wecker-App/1.0 (PHP)\r\n"
            ]
        ]);
        $nomJson = @file_get_contents($nominatimUrl, false, $ctxNom);
        if ($nomJson !== false) {
            $nom = json_decode($nomJson, true);
            if (!empty($nom[0]['lat']) && !empty($nom[0]['lon'])) {
                $lat = (float) $nom[0]['lat'];
                $lon = (float) $nom[0]['lon'];
            }
        }
    }

    if ($lat === null || $lon === null) {
        return ['ok' => false, 'error' => 'Ort nicht gefunden'];
    }

    $forecastUrl = 'https://api.open-meteo.com/v1/forecast?' . http_build_query([
        'latitude' => $lat,
        'longitude' => $lon,
        'current' => 'temperature_2m,weather_code,relative_humidity_2m,apparent_temperature,precipitation,cloud_cover,surface_pressure,wind_speed_10m,wind_direction_10m,visibility',
        'daily' => 'temperature_2m_max,temperature_2m_min,weather_code,sunrise,sunset,precipitation_probability_max,uv_index_max,daylight_duration',
        'timezone' => $tz,
        'forecast_days' => 8
    ]);
    $forecastJson = @file_get_contents($forecastUrl, false, $ctx);
    if ($forecastJson === false) {
        return ['ok' => false, 'error' => 'Wetter nicht erreichbar'];
    }

    $forecast = json_decode($forecastJson, true);
    if (empty($forecast['current'])) {
        return ['ok' => false, 'error' => 'Keine Wetterdaten'];
    }

    $current = $forecast['current'];
    $daily = $forecast['daily'] ?? [];

    $out = [
        'ok' => true,
        'current' => [
            'temp' => round($current['temperature_2m'] ?? 0, 1),
            'beschreibung' => function_wmo_beschreibung($current['weather_code'] ?? 0),
            'code' => (int) ($current['weather_code'] ?? 0),
            'humidity' => isset($current['relative_humidity_2m']) ? (int) $current['relative_humidity_2m'] : null,
            'apparent_temperature' => isset($current['apparent_temperature']) ? round($current['apparent_temperature'], 1) : null,
            'precipitation' => isset($current['precipitation']) ? round($current['precipitation'], 1) : null,
            'cloud_cover' => isset($current['cloud_cover']) ? (int) $current['cloud_cover'] : null,
            'pressure' => isset($current['surface_pressure']) ? round($current['surface_pressure'], 0) : null,
            'wind_speed' => isset($current['wind_speed_10m']) ? round($current['wind_speed_10m'], 0) : null,
            'wind_direction' => isset($current['wind_direction_10m']) ? (int) $current['wind_direction_10m'] : null,
            'visibility' => isset($current['visibility']) ? round($current['visibility'] / 1000, 1) : null,
        ],
        'daily' => []
    ];

    $dailyCount = !empty($daily['time']) ? min(count($daily['time']), 8) : 0;
    for ($i = 0; $i < $dailyCount; $i++) {
        $datum = $daily['time'][$i];
        $wcode = (int) ($daily['weather_code'][$i] ?? 0);
        $sunrise = isset($daily['sunrise'][$i]) ? date('H:i', strtotime($daily['sunrise'][$i])) : null;
        $sunset = isset($daily['sunset'][$i]) ? date('H:i', strtotime($daily['sunset'][$i])) : null;
        $daylight = null;
        if (!empty($daily['daylight_duration'][$i])) {
            $sec = (int) $daily['daylight_duration'][$i];
            $daylight = round($sec / 3600, 1);
        }
        $out['daily'][] = [
            'datum' => date('D, d.m.', strtotime($datum)),
            'datum_short' => date('D', strtotime($datum)),
            'temp_max' => isset($daily['temperature_2m_max'][$i]) ? round($daily['temperature_2m_max'][$i], 0) : null,
            'temp_min' => isset($daily['temperature_2m_min'][$i]) ? round($daily['temperature_2m_min'][$i], 0) : null,
            'beschreibung' => function_wmo_beschreibung($wcode),
            'code' => $wcode,
            'precipitation_probability_max' => isset($daily['precipitation_probability_max'][$i]) ? (int) $daily['precipitation_probability_max'][$i] : null,
            'uv_index_max' => isset($daily['uv_index_max'][$i]) ? round($daily['uv_index_max'][$i], 1) : null,
            'sunrise' => $sunrise,
            'sunset' => $sunset,
            'daylight_duration' => $daylight,
        ];
    }
    if ($dailyCount > 0 && isset($daily['uv_index_max'][0])) {
        $out['current']['uv_index'] = round($daily['uv_index_max'][0], 1);
    }

    if (is_dir($cacheDir) || @mkdir($cacheDir, 0755, true)) {
        $cachePayload = json_encode(['expires' => time() + WETTER_CACHE_TTL, 'data' => $out]);
        if ($cachePayload !== false) {
            @file_put_contents($cacheFile, $cachePayload, LOCK_EX);
        }
    }

    function_cache_set('wetter_' . $cacheKey, $out);
    return $out;
}
