<?php

declare(strict_types=1);

function qrator_update_status_file(): string {
    $dir = __DIR__ . '/../storage';
    if (!is_dir($dir)) { @mkdir($dir, 0755, true); }
    return $dir . '/update_status.json';
}

function qrator_update_status_read(): array {
    $file = qrator_update_status_file();
    if (!is_file($file)) {
        return ['has_update' => false, 'checked_at' => 0, 'latest_version' => '', 'message' => ''];
    }
    $raw = @file_get_contents($file);
    $data = is_string($raw) ? json_decode($raw, true) : null;
    if (!is_array($data)) {
        return ['has_update' => false, 'checked_at' => 0, 'latest_version' => '', 'message' => ''];
    }
    return [
        'has_update' => !empty($data['has_update']),
        'checked_at' => (int)($data['checked_at'] ?? 0),
        'latest_version' => (string)($data['latest_version'] ?? ''),
        'current_version' => (string)($data['current_version'] ?? (defined('QRATOR_VERSION') ? QRATOR_VERSION : '0')),
        'message' => (string)($data['message'] ?? ''),
        'manifest_url' => (string)($data['manifest_url'] ?? (defined('QRATOR_UPDATE_MANIFEST_URL') ? QRATOR_UPDATE_MANIFEST_URL : '')),
    ];
}

function qrator_update_status_write(array $status): void {
    $file = qrator_update_status_file();
    $payload = [
        'has_update' => !empty($status['has_update']),
        'latest_version' => (string)($status['latest_version'] ?? ''),
        'current_version' => (string)($status['current_version'] ?? (defined('QRATOR_VERSION') ? QRATOR_VERSION : '0')),
        'checked_at' => (int)($status['checked_at'] ?? time()),
        'message' => (string)($status['message'] ?? ''),
        'manifest_url' => (string)($status['manifest_url'] ?? (defined('QRATOR_UPDATE_MANIFEST_URL') ? QRATOR_UPDATE_MANIFEST_URL : '')),
    ];
    @file_put_contents($file, json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), LOCK_EX);
}

function qrator_update_normalize_version(string $version): string {
    $version = trim($version);
    $version = ltrim($version, "vV");
    return preg_replace('/[^0-9.\-]/', '', $version) ?: '0';
}

function qrator_update_fetch_manifest(string $url): array {
    $url = trim($url);
    if ($url === '' || !preg_match('#^https://#i', $url)) {
        return [false, 'Keine gültige HTTPS-Adresse für den Update-Check konfiguriert.', null];
    }
    $body = false;
    $status = 0;
    $err = '';
    if (function_exists('curl_init')) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => false,
            CURLOPT_CONNECTTIMEOUT => 3,
            CURLOPT_TIMEOUT => 6,
            CURLOPT_USERAGENT => 'QRator/'.(defined('QRATOR_VERSION') ? QRATOR_VERSION : 'unknown'),
        ]);
        $body = curl_exec($ch);
        $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $err = curl_error($ch);
        curl_close($ch);
        if ($body === false || $status < 200 || $status >= 300) {
            return [false, 'Update-Check fehlgeschlagen'.($err ? ': '.$err : '. HTTP-Status '.$status), null];
        }
    } else {
        $ctx = stream_context_create(['http' => ['timeout' => 6, 'ignore_errors' => true, 'header' => 'User-Agent: QRator/'.(defined('QRATOR_VERSION') ? QRATOR_VERSION : 'unknown')]]);
        $body = @file_get_contents($url, false, $ctx);
        if ($body === false) {
            return [false, 'Update-Check fehlgeschlagen. Der Server konnte update.json nicht lesen.', null];
        }
    }
    if (strlen((string)$body) > 64 * 1024) {
        return [false, 'Update-Manifest ist zu gross und wurde abgelehnt.', null];
    }
    $data = json_decode((string)$body, true);
    if (!is_array($data)) {
        $jsonError = function_exists('json_last_error_msg') ? json_last_error_msg() : 'JSON-Fehler';
        return [false, 'Update-Manifest ist kein gültiges JSON: '.$jsonError, null];
    }
    return [true, '', $data];
}

function qrator_update_refresh_status(bool $force = false, int $ttlSeconds = 1800): array {
    $now = time();
    $cached = qrator_update_status_read();
    if (!$force && !empty($cached['checked_at']) && ($now - (int)$cached['checked_at']) < $ttlSeconds) {
        return $cached;
    }

    $url = defined('QRATOR_UPDATE_MANIFEST_URL') ? (string)QRATOR_UPDATE_MANIFEST_URL : 'https://qrator.web2use.ch/update.json';
    [$ok, $message, $data] = qrator_update_fetch_manifest($url);
    $current = qrator_update_normalize_version(defined('QRATOR_VERSION') ? (string)QRATOR_VERSION : '0');

    if (!$ok || !is_array($data)) {
        $status = [
            'has_update' => false,
            'latest_version' => '',
            'current_version' => $current,
            'checked_at' => $now,
            'message' => $message,
            'manifest_url' => $url,
        ];
        qrator_update_status_write($status);
        return $status;
    }

    $expectedChannel = defined('QRATOR_UPDATE_CHANNEL') ? (string)QRATOR_UPDATE_CHANNEL : '';
    $manifestChannel = (string)($data['channel'] ?? '');
    if ($expectedChannel !== '' && $manifestChannel !== '' && $manifestChannel !== $expectedChannel) {
        $status = [
            'has_update' => false,
            'latest_version' => '',
            'current_version' => $current,
            'checked_at' => $now,
            'message' => 'Update-Kanal passt nicht zur Installation.',
            'manifest_url' => $url,
        ];
        qrator_update_status_write($status);
        return $status;
    }

    $latest = qrator_update_normalize_version((string)($data['latest_version'] ?? ''));
    $status = [
        'has_update' => $latest !== '0' && version_compare($latest, $current, '>'),
        'latest_version' => $latest,
        'current_version' => $current,
        'checked_at' => $now,
        'message' => '',
        'manifest_url' => $url,
        'channel' => $manifestChannel,
    ];
    qrator_update_status_write($status);
    return $status;
}

function qrator_update_badge_html(): string {
    $status = qrator_update_refresh_status(false, 1800);
    if (!empty($status['has_update'])) {
        return '<span class="nav-badge nav-badge-update" title="Neues Update verfügbar">1</span>';
    }
    return '';
}

function qrator_update_clear_status(): void {
    qrator_update_status_write([
        'has_update' => false,
        'latest_version' => '',
        'current_version' => defined('QRATOR_VERSION') ? (string)QRATOR_VERSION : '0',
        'checked_at' => time(),
        'message' => '',
        'manifest_url' => defined('QRATOR_UPDATE_MANIFEST_URL') ? (string)QRATOR_UPDATE_MANIFEST_URL : '',
    ]);
}
