<?php
define('RWS_VERSION', '1.2');
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

// Ultimátní záchytná síť pro Fatální chyby - vynutí zobrazení chyby přímo v prohlížeči i přes omezení hostingu
register_shutdown_function(function() {
    $err = error_get_last();
    if ($err !== null && in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        http_response_code(500);
        echo "<div style='background:#ff4b2b; color:#fff; padding:20px; font-family:sans-serif; position:fixed; top:0; left:0; width:100%; z-index:999999;'>";
        echo "<h2 style='margin-top:0;'>Kritická chyba systému (Fatal Error)</h2>";
        echo "<b>Chyba:</b> " . htmlspecialchars($err['message']) . "<br><br>";
        echo "<b>Soubor:</b> " . htmlspecialchars($err['file']) . "<br>";
        echo "<b>Řádek:</b> " . htmlspecialchars($err['line']);
        echo "</div>";
    }
});
session_start();

// Definice systémových jazyků
$sysLangsAll = ['cs'=>'Čeština', 'en'=>'English', 'de'=>'Deutsch', 'fr'=>'Français', 'es'=>'Español', 'hu'=>'Magyar', 'pt'=>'Português', 'ru'=>'Русский', 'uk'=>'Українська', 'zh'=>'中文', 'ja'=>'日本語', 'vi'=>'Tiếng Việt'];
$flagCodes = ['cs'=>'cz', 'en'=>'gb', 'de'=>'de', 'fr'=>'fr', 'es'=>'es', 'hu'=>'hu', 'pt'=>'pt', 'ru'=>'ru', 'uk'=>'ua', 'zh'=>'cn', 'ja'=>'jp', 'vi'=>'vn'];
$activeLangs = array_keys($sysLangsAll);

require_once __DIR__ . '/JsonDB.php';
$settingsDbGlobal = new JsonDB('settings');
foreach ($settingsDbGlobal->getAll() as $row) {
    if (is_array($row) && isset($row['key']) && $row['key'] === 'active_langs' && is_array($row['value'])) {
        $activeLangs = $row['value']; break;
    }
}
$sysLangs = [];
foreach ($sysLangsAll as $k => $v) { if (in_array($k, $activeLangs)) $sysLangs[$k] = $v; }

/**
 * RadioWebSystem - Administrace a API
 */

// Zakázání cachování globálně pro celou aplikaci
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Expires: 0");


// Získání cesty z .htaccess (např. dashboard nebo api/endpoint)
$route = isset($_GET['route']) && $_GET['route'] !== '' ? trim($_GET['route'], '/') : 'dashboard';
$routeParts = explode('/', $route);
$mainSection = $routeParts[0];

$usersDb = new JsonDB('users');
if (empty($usersDb->getAll())) {
    $usersDb->insert(['username' => 'admin', 'password' => password_hash('admin', PASSWORD_DEFAULT), 'name' => 'Hlavní Administrátor', 'role' => 'admin', 'modules' => []]);
}

if ($mainSection === 'logout') { session_destroy(); header('Location: /admin'); exit; }

$currentUser = $_SESSION['rws_user'] ?? null;
if (!is_array($currentUser)) $currentUser = null;

function hasAccess($module) {
    global $currentUser;
    if (!$currentUser) return false;
    if (($currentUser['role'] ?? '') === 'admin') return true;
    if (empty($currentUser['modules']) || !is_array($currentUser['modules'])) return false;
    return in_array($module, $currentUser['modules']);
}

function logActivity($action, $details = '') {
    global $currentUser;
    if (!$currentUser) return;
    $logDb = new JsonDB('activity_log');
    $logDb->insert([
        'user' => $currentUser['username'],
        'role' => $currentUser['role'],
        'action' => $action,
        'details' => $details
    ]);
}

    // Funkce pro overeni reCAPTCHA
    if (!function_exists('verifyRecaptcha')) {
        function verifyRecaptcha($input) {
            $settingsDb = new JsonDB('settings');
            $secret = '';
            foreach ($settingsDb->getAll() as $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'recaptcha_secret_key') { $secret = $row['value']; break; } }
            if (!empty($secret)) {
                $token = $input['recaptcha_token'] ?? '';
                if (!$token) return false;
                $verifyResponse = @file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($secret) . '&response=' . urlencode($token));
                $responseData = json_decode($verifyResponse);
                if (!$responseData || empty($responseData->success) || ($responseData->score ?? 1) < 0.5) return false;
            }
            return true;
        }
    }

// API Router pro backendové AJAX požadavky
if ($mainSection === 'api') {
    ob_start(); // Ochrana před PHP varováními, aby nerozbila JSON odpověď
    header('Content-Type: application/json; charset=utf-8');
    $response = ['status' => 'error', 'message' => 'Neznámý endpoint'];
    
    try {
        $endpoint = $routeParts[1] ?? '';
        $method = $_SERVER['REQUEST_METHOD'];

        // Vložení GoAccess proxy před JSON hlavičkou pro nativní vrácení HTML stránky do Iframe
        if ($endpoint === 'goaccess-proxy') {
            if (!$currentUser) { header('HTTP/1.1 401 Unauthorized'); exit('Unauthorized'); }
            ob_clean();
            header('Content-Type: text/html; charset=utf-8');
            $statsFileWeb = __DIR__ . '/stats/goaindex.html';
            $statsFileAbove = __DIR__ . '/../stats/goaindex.html';
            if (@file_exists($statsFileWeb)) { echo @file_get_contents($statsFileWeb); }
            elseif (@file_exists($statsFileAbove)) { echo @file_get_contents($statsFileAbove); }
            else { echo "<div style='color:#333; font-family:sans-serif; text-align:center; padding:50px;'><h2>GoAccess statistiky nenalezeny</h2><p>Pravděpodobně brání restrikce <code>open_basedir</code>, nebo soubor neexistuje ve složce stats. Zkontrolujte nastavení hostingu.</p></div>"; }
            exit;
        }

        if ($endpoint === 'login') {
            $input = json_decode(file_get_contents('php://input'), true); if (!is_array($input)) $input = [];
            foreach ($usersDb->getAll() as $u) {
                if (is_array($u) && isset($u['username']) && $u['username'] === ($input['username'] ?? '') && password_verify($input['password'] ?? '', $u['password'] ?? '')) {
                    $_SESSION['rws_user'] = $u; echo json_encode(['status' => 'success']); exit;
                }
            }
            echo json_encode(['status' => 'error', 'message' => 'Špatné jméno nebo heslo.']); exit;
        }
        
        $debugLog = ob_get_clean();
        if (!empty(trim($debugLog))) { $response['debug_warnings'] = trim(strip_tags($debugLog)); }

        $isPublic = false;
        if (($endpoint === 'contact' && $method === 'POST') || ($endpoint === 'requests' && $method === 'POST') || ($endpoint === 'webhook' && $method === 'POST')) $isPublic = true;
        if (in_array($endpoint, ['onair', 'songs', 'stats', 'template-config', 'settings-config', 'boxes', 'menus', 'pages', 'podcasts']) && $method === 'GET') $isPublic = true;
        if (!$currentUser && !$isPublic) {
            echo json_encode(['status' => 'error', 'message' => 'Neautorizováno.']); exit;
        }
    
    // CRUD logika pro moderátory
    if ($endpoint === 'moderators') {
        $db = new JsonDB('moderators');
        $method = $_SERVER['REQUEST_METHOD'];
        
        if ($method === 'GET') {
            $response = ['status' => 'success', 'data' => array_values($db->getAll())];
        } elseif ($method === 'POST') {
            $input = json_decode(file_get_contents('php://input'), true);
            if (!is_array($input)) $input = [];
            if (!empty($input) && isset($input['name'])) {
                $password = $input['password'] ?? '';
                unset($input['password']); // Heslo se neukládá do databáze moderátorů

                // Synchronizace s uživatelským účtem
                if (!empty($input['email'])) {
                    $usersDb = new JsonDB('users');
                    $targetUid = null;
                    foreach ($usersDb->getAll() as $uid => $u) {
                        if (is_array($u) && ($u['username'] ?? '') === $input['email']) { $targetUid = $uid; break; }
                    }
                    if ($targetUid) {
                        $uData = ['name' => $input['name']];
                        if (!empty($password)) $uData['password'] = password_hash($password, PASSWORD_DEFAULT);
                        $usersDb->update($targetUid, $uData);
                    } elseif (!empty($password)) {
                        $usersDb->insert([
                            'username' => $input['email'],
                            'password' => password_hash($password, PASSWORD_DEFAULT),
                            'name' => $input['name'],
                            'role' => 'moderator',
                            'modules' => ['dashboard', 'requests', 'requests-studio', 'songs', 'calendar', 'moderator-profile']
                        ]);
                    }
                }

                if (isset($input['photo_base64'])) {
                    if (!empty($input['photo_base64']) && strpos($input['photo_base64'], 'data:image') === 0) {
                        $mediaDir = __DIR__ . '/media';
                        if (!file_exists($mediaDir)) mkdir($mediaDir, 0777, true);
                        list($type, $data) = explode(';', $input['photo_base64']);
                        list(, $data)      = explode(',', $data);
                        $data = base64_decode($data);
                        $ext = strpos($type, 'png') !== false ? 'png' : (strpos($type, 'webp') !== false ? 'webp' : 'jpg');
                        $filename = 'mod_' . uniqid() . '.' . $ext;
                        file_put_contents($mediaDir . '/' . $filename, $data);
                        $input['photo'] = 'media/' . $filename;
                    }
                    unset($input['photo_base64']);
                }
                if (isset($input['id']) && !empty($input['id'])) {
                    $id = $input['id'];
                    unset($input['id']);
                    if ($db->update($id, $input)) {
                        logActivity('Upraven moderátor', $input['name'] ?? '');
                        $response = ['status' => 'success', 'message' => 'Moderátor upraven.'];
                    } else {
                        $response = ['status' => 'error', 'message' => 'Moderátor nenalezen.'];
                    }
                } else {
                    unset($input['id']);
                    $id = $db->insert($input);
                    logActivity('Vytvořen moderátor', $input['name'] ?? '');
                    $response = ['status' => 'success', 'message' => 'Moderátor přidán.', 'id' => $id];
                }
            } else {
                $response = ['status' => 'error', 'message' => 'Chybí povinné údaje.'];
            }
        } elseif ($method === 'DELETE') {
            $input = json_decode(file_get_contents('php://input'), true);
            if (!is_array($input)) $input = [];
            if (isset($input['id'])) {
                $mod = $db->getById($input['id']);
                if ($mod && !empty($mod['is_autopilot'])) {
                    $response = ['status' => 'error', 'message' => 'Autopilota nelze smazat.'];
                } elseif ($db->delete($input['id'])) {
                    logActivity('Smazán moderátor', $mod['name'] ?? $input['id']);
                    $response = ['status' => 'success', 'message' => 'Moderátor smazán.'];
                } else {
                    $response = ['status' => 'error', 'message' => 'Chyba při mazání.'];
                }
            }
        }
    }
    
    // CRUD logika pro kalendář (směny)
    if ($endpoint === 'calendar') {
        $db = new JsonDB('shifts');
        $method = $_SERVER['REQUEST_METHOD'];
        
        if ($method === 'GET') {
            $response = ['status' => 'success', 'data' => array_values($db->getAll())];
        } elseif ($method === 'POST') {
            $input = json_decode(file_get_contents('php://input'), true);
            if (!is_array($input)) $input = [];
            if (!empty($input) && isset($input['date']) && isset($input['hour'])) {
                $existing = $db->getAll();
                $targetId = null;
                foreach ($existing as $id => $shift) {
                    if ($shift['date'] === $input['date'] && (int)$shift['hour'] === (int)$input['hour']) {
                        $targetId = $id; break;
                    }
                }
                
                $mods = $input['moderator_ids'] ?? [];
                if (empty($mods)) {
                    if ($targetId) $db->delete($targetId);
                } else {
                    $data = ['date' => $input['date'], 'hour' => (int)$input['hour'], 'moderator_ids' => $mods];
                    $targetId ? $db->update($targetId, $data) : $db->insert($data);
                }
                logActivity('Změna ve směnách', "Datum: {$input['date']}, Hodina: {$input['hour']}");
                $response = ['status' => 'success', 'message' => 'Směna uložena.'];
            }
        }
    }

    // Logika pro DashBoard (Aktuálně ON-AIR)
    if ($endpoint === 'onair') {
        $shiftsDb = new JsonDB('shifts');
        $modsDb = new JsonDB('moderators');
        $settingsDb = new JsonDB('settings');
        $method = $_SERVER['REQUEST_METHOD'];

        if ($method === 'GET') {
            $currentDate = date('Y-m-d');
            $currentHour = (int)date('H');
            
            $scheduledModIds = [];
            foreach ($shiftsDb->getAll() as $shift) {
                if (is_array($shift) && isset($shift['date']) && $shift['date'] === $currentDate && (int)$shift['hour'] === $currentHour) {
                    $scheduledModIds = $shift['moderator_ids'] ?? []; break;
                }
            }

            $overrideRecord = null;
            $targetOverrideId = null;
            foreach ($settingsDb->getAll() as $id => $row) {
                if (is_array($row) && isset($row['key']) && $row['key'] === 'onair_override') {
                    $overrideRecord = $row;
                    $targetOverrideId = $id;
                    break;
                }
            }

            $isOverride = false;
            $activeModIds = $scheduledModIds;
            
            if ($overrideRecord) {
                if (isset($overrideRecord['valid_until']) && time() < $overrideRecord['valid_until']) {
                    $val = $overrideRecord['value'] ?? [];
                    $activeModIds = (is_array($val) ? ($val['moderator_ids'] ?? []) : []) ?: ($overrideRecord['moderator_ids'] ?? []);
                    $isOverride = true;
                } else {
                    $settingsDb->delete($targetOverrideId);
                }
            }

            $activeMods = [];
            foreach ($activeModIds as $modId) {
                $mod = $modsDb->getById($modId);
                if ($mod) $activeMods[] = $mod;
            }

            $isAutopilot = false;
            if (empty($activeMods)) {
                $autopilot = null;
                foreach ($modsDb->getAll() as $m) { if (!empty($m['is_autopilot'])) { $autopilot = $m; break; } }
                if (!$autopilot) {
                    $autoId = $modsDb->insert(['name' => '🤖 DJ Autopilot', 'active' => true, 'is_autopilot' => true, 'short_desc' => 'Automatické vysílání']);
                    $autopilot = $modsDb->getById($autoId);
                }
                $activeMods[] = $autopilot;
                $isAutopilot = true;
            }
            
            $statsDb = new JsonDB('stats');
            $allStats = array_values($statsDb->getAll());
            usort($allStats, function($a, $b) { return strtotime($b['timestamp']) <=> strtotime($a['timestamp']); });
            $wsDb = new JsonDB('web_stats');
            $totalViews = 0;
            $totalUnique = 0;
            foreach ($wsDb->getAll() as $ws) {
                if (is_array($ws)) {
                    $totalViews += ($ws['views'] ?? 0);
                    $totalUnique += ($ws['unique'] ?? 0);
                }
            }

            $response = [
                'status' => 'success',
                'data' => [
                    'mods' => $activeMods,
                    'is_override' => $isOverride,
                    'is_autopilot' => $isAutopilot,
                    'current_hour' => $currentHour,
                    'web_views' => $totalViews,
                    'web_unique' => $totalUnique,
                    'current_listeners' => !empty($allStats) ? (int)$allStats[0]['listeners'] : 0
                ]
            ];
        } elseif ($method === 'POST') {
            $input = json_decode(file_get_contents('php://input'), true);
            if (!is_array($input)) $input = [];
            
            $targetOverrideId = null;
            foreach ($settingsDb->getAll() as $id => $row) {
                if (is_array($row) && isset($row['key']) && $row['key'] === 'onair_override') {
                    $targetOverrideId = $id; break;
                }
            }

            if (isset($input['clear']) && $input['clear'] === true) {
                if ($targetOverrideId) $settingsDb->delete($targetOverrideId);
                $response = ['status' => 'success', 'message' => 'Ruční režim zrušen.'];
            } else {
                $validUntil = strtotime(date('Y-m-d H:00:00', strtotime('+1 hour')));
                $data = [
                    'key' => 'onair_override',
                    'value' => [
                        'moderator_ids' => $input['moderator_ids'] ?? []
                    ],
                    'valid_until' => $validUntil
                ];
                $targetOverrideId ? $settingsDb->update($targetOverrideId, $data) : $settingsDb->insert($data);
                $response = ['status' => 'success', 'message' => 'Ruční moderátor nastaven.'];
            }
        }
    }

    // AI Translate endpoint
    if ($endpoint === 'ai-translate' && $method === 'POST') {
        $input = json_decode(file_get_contents('php://input'), true);
        if (!is_array($input)) $input = [];
        
        $settingsDb = new JsonDB('settings');
        $aiProvider = 'openai'; $openAiKey = ''; $geminiKey = ''; $geminiModel = 'gemini-2.5-flash';
        foreach ($settingsDb->getAll() as $row) {
            if (is_array($row)) {
                if (($row['key'] ?? '') === 'ai_provider') $aiProvider = $row['value'];
                if (($row['key'] ?? '') === 'openai_api_key') $openAiKey = $row['value'];
                if (($row['key'] ?? '') === 'gemini_api_key') $geminiKey = $row['value'];
                if (($row['key'] ?? '') === 'gemini_model') $geminiModel = $row['value'];
            }
        }
        
        $title = $input['title'] ?? ''; $content = $input['content'] ?? ''; $langs = $input['langs'] ?? [];
        if (empty($langs) || empty($title) || empty($content)) { echo json_encode(['status' => 'error', 'message' => 'Chybí data k překladu.']); exit; }

        $systemPrompt = "You are a professional translator. Translate the following article into the requested languages. The text contains HTML tags. Keep the HTML tags intact, only translate the text inside them. The output MUST be a STRICT, valid JSON object where keys are language codes and values are objects with 'title', 'slug' (url friendly), and 'content' keys. Escape all quotes and use \\n for newlines inside strings. Do NOT wrap the JSON in markdown! E.g. {\"en\": {\"title\": \"...\", \"slug\": \"...\", \"content\": \"...\"}}.\n\nTarget languages: " . implode(', ', $langs);
        $systemPrompt .= "\n\nCRITICAL: If the input is extremely long, you MUST complete the JSON structure properly. Do NOT cut off the JSON. Provide as much translation as fits in the token limit, but close all brackets.";
        $userPrompt = "Title to translate:\n$title\n\nContent to translate:\n$content";

        $responseObj = null;

        if ($aiProvider === 'gemini' && !empty($geminiKey)) {
            $url = "https://generativelanguage.googleapis.com/v1beta/models/{$geminiModel}:generateContent?key=" . $geminiKey;
            $payload = [
                "system_instruction" => ["parts" => [["text" => $systemPrompt]]],
                "contents" => [["parts" => [["text" => $userPrompt]]]],
                "generationConfig" => ["response_mime_type" => "application/json", "maxOutputTokens" => 8192]
            ];
            $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); $res = curl_exec($ch); if(PHP_VERSION_ID < 80000) curl_close($ch);
            $json = json_decode($res, true);
            if (isset($json['error'])) { echo json_encode(['status' => 'error', 'message' => 'Gemini API Chyba: ' . ($json['error']['message'] ?? 'Neznámá chyba')]); exit; }
            $text = $json['candidates'][0]['content']['parts'][0]['text'] ?? '';
            if (preg_match('/```(?:json)?\s*(.*?)\s*```/s', $text, $matches)) { $text = $matches[1]; }
            $start = strpos($text, '{'); $end = strrpos($text, '}');
            if ($start !== false && $end !== false) $text = substr($text, $start, $end - $start + 1);
            $responseObj = json_decode($text, true);
        } elseif ($aiProvider === 'openai' && !empty($openAiKey)) {
            $url = "https://api.openai.com/v1/chat/completions";
            $payload = [
                "model" => "gpt-4o-mini", "response_format" => ["type" => "json_object"],
                "max_tokens" => 8192,
                "messages" => [ ["role" => "system", "content" => $systemPrompt], ["role" => "user", "content" => $userPrompt] ]
            ];
            $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Authorization: Bearer ' . $openAiKey]); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); $res = curl_exec($ch); if(PHP_VERSION_ID < 80000) curl_close($ch);
            $json = json_decode($res, true);
            if (isset($json['error'])) { echo json_encode(['status' => 'error', 'message' => 'OpenAI API Chyba: ' . ($json['error']['message'] ?? 'Neznámá chyba')]); exit; }
            $text = $json['choices'][0]['message']['content'] ?? '';
            if (preg_match('/```(?:json)?\s*(.*?)\s*```/s', $text, $matches)) { $text = $matches[1]; }
            $start = strpos($text, '{'); $end = strrpos($text, '}');
            if ($start !== false && $end !== false) $text = substr($text, $start, $end - $start + 1);
            $responseObj = json_decode($text, true);
        } else {
            echo json_encode(['status' => 'error', 'message' => 'Není nastaven API klíč pro zvoleného AI providera.']); exit;
        }

        if ($responseObj) { 
            echo json_encode(['status' => 'success', 'data' => $responseObj]); 
        } else { 
            $err = json_last_error_msg();
            echo json_encode(['status' => 'error', 'message' => "AI nevrátila platný JSON ($err). Zkuste to znovu.\n\nRaw odpověď od AI:\n" . ($text ?? 'Žádná odpověď.')]); 
        }
        exit;
    }

    // API endpoint pro test AI
    if ($endpoint === 'ai-test' && $method === 'POST') {
        $input = json_decode(file_get_contents('php://input'), true);
        $provider = $input['ai_provider'] ?? 'openai';
        $openAiKey = $input['openai_api_key'] ?? '';
        $geminiKey = $input['gemini_api_key'] ?? '';
        $geminiModel = $input['gemini_model'] ?? 'gemini-2.5-flash';
        
        $responseObj = null;
        if ($provider === 'gemini' && !empty($geminiKey)) {
            $url = "https://generativelanguage.googleapis.com/v1beta/models/{$geminiModel}:generateContent?key=" . $geminiKey;
            $payload = [
                "contents" => [["parts" => [["text" => "Reply with a valid JSON object: {\"status\": \"ok\"}"]]]],
                "generationConfig" => ["response_mime_type" => "application/json"]
            ];
            $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); $res = curl_exec($ch); if(PHP_VERSION_ID < 80000) curl_close($ch);
            $json = json_decode($res, true);
            if (isset($json['error'])) { echo json_encode(['status' => 'error', 'message' => 'API Chyba: ' . ($json['error']['message'] ?? 'Neznámá chyba')]); exit; }
            $text = $json['candidates'][0]['content']['parts'][0]['text'] ?? '';
            if (preg_match('/```(?:json)?\s*(.*?)\s*```/s', $text, $matches)) { $text = $matches[1]; }
            $start = strpos($text, '{'); $end = strrpos($text, '}');
            if ($start !== false && $end !== false) $text = substr($text, $start, $end - $start + 1);
            $responseObj = json_decode($text, true);
        } elseif ($provider === 'openai' && !empty($openAiKey)) {
            $url = "https://api.openai.com/v1/chat/completions";
            $payload = [
                "model" => "gpt-4o-mini", "response_format" => ["type" => "json_object"],
                "messages" => [ ["role" => "user", "content" => "Reply with a valid JSON object: {\"status\": \"ok\"}"] ]
            ];
            $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Authorization: Bearer ' . $openAiKey]); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); $res = curl_exec($ch); if(PHP_VERSION_ID < 80000) curl_close($ch);
            $json = json_decode($res, true);
            if (isset($json['error'])) { echo json_encode(['status' => 'error', 'message' => 'API Chyba: ' . ($json['error']['message'] ?? 'Neznámá chyba')]); exit; }
            $text = $json['choices'][0]['message']['content'] ?? '';
            if (preg_match('/```(?:json)?\s*(.*?)\s*```/s', $text, $matches)) { $text = $matches[1]; }
            $start = strpos($text, '{'); $end = strrpos($text, '}');
            if ($start !== false && $end !== false) $text = substr($text, $start, $end - $start + 1);
            $responseObj = json_decode($text, true);
        } else {
            echo json_encode(['status' => 'error', 'message' => 'Není nastaven API klíč pro zvoleného AI providera.']); exit;
        }

        if ($responseObj && isset($responseObj['status'])) { 
            echo json_encode(['status' => 'success', 'message' => 'Připojení k AI bylo úspěšné. Komunikace funguje.']); 
        } else { 
            echo json_encode(['status' => 'error', 'message' => 'AI vrátila nečitelná data. Zkontrolujte klíč a model.']); 
        }
        exit;
    }

    // Logika pro Kartu moderátora
    if ($endpoint === 'moderator-profile') {
        $modId = $_GET['id'] ?? '';
        $modsDb = new JsonDB('moderators');
        $shiftsDb = new JsonDB('shifts');
        
        $mod = $modsDb->getById($modId);
        if (!$mod) {
            $response = ['status' => 'error', 'message' => 'Moderátor nenalezen.'];
        } else {
            $allShifts = $shiftsDb->getAll();
            $modShifts = [];
            foreach ($allShifts as $shift) {
                if (isset($shift['moderator_ids']) && in_array($modId, $shift['moderator_ids'])) {
                    $modShifts[] = $shift;
                }
            }
            
            usort($modShifts, function($a, $b) {
                $timeA = strtotime($a['date'] . ' ' . $a['hour'] . ':00:00');
                $timeB = strtotime($b['date'] . ' ' . $b['hour'] . ':00:00');
                return $timeA <=> $timeB;
            });
            
            $response = [
                'status' => 'success', 
                'data' => ['moderator' => $mod, 'shifts' => $modShifts]
            ];
        }
    }

    // Univerzální CRUD pro CRM, Reklamy, Menu, Stránky a Přání, Newsletter a Formuláře
    $crudEndpoints = ['customers', 'ad_spaces', 'campaigns', 'menus', 'pages', 'requests', 'podcasts', 'users', 'banned_ips', 'ignored_songs', 'newsletter', 'forms'];
    if (in_array($endpoint, $crudEndpoints)) {
        $db = new JsonDB($endpoint);
        $method = $_SERVER['REQUEST_METHOD'];
        if ($method === 'GET') {
            $response = ['status' => 'success', 'data' => array_values($db->getAll())];
        } elseif ($method === 'POST') {
            $input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
            if (!is_array($input)) $input = [];
            if (!empty($input)) {
                if ($endpoint === 'requests') {
                    if (!verifyRecaptcha($input)) { echo json_encode(['status' => 'error', 'message' => 'Spam detekován (Ochrana).']); exit; }
                    $userIp = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
                    $bannedDb = new JsonDB('banned_ips');
                    foreach ($bannedDb->getAll() as $b) { if (($b['ip'] ?? '') === $userIp) { echo json_encode(['status' => 'success']); exit; } }
                    $input['ip'] = $userIp;
                    $input['created_at'] = date('Y-m-d H:i:s');
                    $db->insert($input);
                    
                    // Odeslání e-mailu do studia a posluchači
                    $settingsDb = new JsonDB('settings');
                    $autoloadPath = __DIR__ . '/vendor/autoload.php';
                    if (file_exists($autoloadPath)) {
                        require_once $autoloadPath;
                        try {
                            $mail = new \PHPMailer\PHPMailer\PHPMailer(true);
                            $mail->CharSet = 'UTF-8'; $mail->Timeout = 5; $mail->SMTPDebug = 0;
                            $smtpConfig = null; $tpl = ['color_accent' => '#00d2ff', 'color_bg1' => '#1e3c72', 'color_bg2' => '#2a5298'];
                            foreach ($settingsDb->getAll() as $row) { 
                                if (is_array($row) && isset($row['key']) && $row['key'] === 'smtp') { $smtpConfig = $row['value']; }
                                if (is_array($row) && isset($row['key']) && $row['key'] === 'template' && is_array($row['value'])) { $tpl = array_merge($tpl, $row['value']); }
                            }
                            if ($smtpConfig && !empty($smtpConfig['host'])) {
                                $mail->isSMTP(); $mail->Host = $smtpConfig['host']; $mail->SMTPAuth = true;
                                $mail->Username = $smtpConfig['username'] ?? ''; $mail->Password = $smtpConfig['password'] ?? '';
                                $mail->SMTPSecure = $smtpConfig['encryption'] === 'tls' ? \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS : ($smtpConfig['encryption'] === 'ssl' ? \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS : '');
                                $mail->Port = (int)$smtpConfig['port'];
                            }
                            $fromEmail = !empty($smtpConfig['from_email']) ? $smtpConfig['from_email'] : 'info@radiowebsystem.local';
                            $fromName = !empty($smtpConfig['from_name']) ? $smtpConfig['from_name'] : 'RadioWebSystem';
                            
                            $senderEmail = $input['email'] ?? ''; $senderName = $input['name'] ?? 'Posluchač'; $song = $input['song'] ?? ''; $message = $input['message'] ?? '';
                            
                            $htmlBody = "<div style='font-family: sans-serif; max-width: 600px; margin: 0 auto; background: linear-gradient(135deg, {$tpl['color_bg1']} 0%, {$tpl['color_bg2']} 100%); padding: 20px; border-radius: 15px; color: #fff;'><div style='background: rgba(255,255,255,0.1); padding: 20px; border-radius: 10px; border: 1px solid rgba(255,255,255,0.2); text-align: left;'><h2 style='color: {$tpl['color_accent']}; margin-top: 0;'>🎵 Písnička na přání</h2><p><strong>Od:</strong> ".htmlspecialchars($senderName)."</p><p><strong>Písnička:</strong> ".htmlspecialchars($song)."</p><p><strong>Vzkaz:</strong><br>".nl2br(htmlspecialchars($message))."</p></div></div>";

                            $mail->setFrom($fromEmail, $fromName);
                            $mail->addAddress($fromEmail, 'Studio');
                            if (!empty($senderEmail) && filter_var($senderEmail, FILTER_VALIDATE_EMAIL)) $mail->addReplyTo($senderEmail, $senderName);
                            $mail->isHTML(true); $mail->Subject = "Nové přání do studia: " . htmlspecialchars($song); $mail->Body = $htmlBody;
                            $mail->send();
                            
                            if (!empty($senderEmail) && filter_var($senderEmail, FILTER_VALIDATE_EMAIL)) {
                                $mail->clearAllRecipients(); $mail->clearReplyTos();
                                $mail->addAddress($senderEmail, $senderName);
                                $mail->Subject = "Potvrzení: Písnička na přání do studia";
                                $mail->Body = "<div style='font-family: sans-serif; max-width: 600px; margin: 0 auto; background: linear-gradient(135deg, {$tpl['color_bg1']} 0%, {$tpl['color_bg2']} 100%); padding: 20px; border-radius: 15px; color: #fff;'><div style='background: rgba(255,255,255,0.1); padding: 20px; border-radius: 10px; border: 1px solid rgba(255,255,255,0.2); text-align: left;'><h2 style='color: {$tpl['color_accent']}; margin-top: 0;'>Děkujeme za Váš vzkaz</h2><p>Vaše písnička a vzkaz byly úspěšně doručeny do studia!</p><p><strong>Písnička:</strong> ".htmlspecialchars($song)."</p><p><strong>Vzkaz:</strong><br>".nl2br(htmlspecialchars($message))."</p></div></div>";
                                $mail->send();
                            }
                        } catch (\Throwable $e) { } // Ignore email errors for requests
                    }
                    echo json_encode(['status' => 'success', 'message' => 'Uloženo a odesláno.']); exit;
                }

                if ($endpoint === 'users') {
                    if (!empty($input['password'])) { $input['password'] = password_hash($input['password'], PASSWORD_DEFAULT); } 
                    else { unset($input['password']); }
                    if (isset($input['modules']) && is_string($input['modules'])) { $input['modules'] = json_decode($input['modules'], true); }
                }

                if ($endpoint === 'customers') {
                    $password = $input['password'] ?? '';
                    unset($input['password']); // Heslo se neukládá do databáze CRM
                    if (!empty($input['email'])) {
                        $usersDb = new JsonDB('users');
                        $targetUid = null;
                        foreach ($usersDb->getAll() as $uid => $u) {
                            if (is_array($u) && ($u['username'] ?? '') === $input['email']) { $targetUid = $uid; break; }
                        }
                        if ($targetUid) {
                            $uData = ['name' => $input['name']];
                            if (!empty($password)) $uData['password'] = password_hash($password, PASSWORD_DEFAULT);
                            $usersDb->update($targetUid, $uData);
                        } elseif (!empty($password)) {
                            $role = ($input['type'] ?? '') === 'sales' ? 'sales' : 'customer';
                            $modules = $role === 'sales' ? ['dashboard', 'ads', 'stats'] : ['dashboard', 'ads'];
                            $usersDb->insert(['username' => $input['email'], 'password' => password_hash($password, PASSWORD_DEFAULT), 'name' => $input['name'], 'role' => $role, 'modules' => $modules]);
                        }
                    }
                }

                $mediaDir = __DIR__ . '/media';
                if (!file_exists($mediaDir)) mkdir($mediaDir, 0777, true);

                if (isset($_FILES['audio']) && $_FILES['audio']['error'] === UPLOAD_ERR_OK) {
                    $ext = pathinfo($_FILES['audio']['name'], PATHINFO_EXTENSION);
                    $filename = 'pod_' . uniqid() . '.' . $ext;
                    move_uploaded_file($_FILES['audio']['tmp_name'], $mediaDir . '/' . $filename);
                    $input['audio_url'] = 'media/' . $filename;
                }

                if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
                    $ext = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
                    $filename = 'img_' . uniqid() . '.' . $ext;
                    move_uploaded_file($_FILES['image']['tmp_name'], $mediaDir . '/' . $filename);
                    $input['image'] = 'media/' . $filename;
                }

                if ($endpoint === 'pages') {
                    if (!empty($input['is_home'])) {
                        $input['is_home'] = true;
                        foreach ($db->getAll() as $pid => $p) {
                            if (!empty($p['is_home']) && $pid !== ($input['id'] ?? '')) { $p['is_home'] = false; $db->update($pid, $p); }
                        }
                    } else {
                        $input['is_home'] = false;
                    }
                }

                if (isset($input['id']) && $input['id'] !== '') {
                    $id = $input['id']; 
                    unset($input['id']);
                    $db->update($id, $input);
                    logActivity("Upraveno: $endpoint", $input['title'] ?? $input['name'] ?? $input['label'] ?? "ID: $id");
                } else {
                    unset($input['id']);
                    $db->insert($input);
                    logActivity("Vytvořeno: $endpoint", $input['title'] ?? $input['name'] ?? $input['label'] ?? "Nový záznam");
                }
                $response = ['status' => 'success', 'message' => 'Uloženo.'];
            }
        } elseif ($method === 'DELETE') {
            $input = json_decode(file_get_contents('php://input'), true);
            if (!is_array($input)) $input = [];
            if (isset($input['id']) && $db->delete($input['id'])) {
                logActivity("Smazáno: $endpoint", "ID: " . $input['id']);
                $response = ['status' => 'success'];
            }
        }
    }

    // IP Ban endpoint
    if ($endpoint === 'ban-ip' && $method === 'POST') {
        $input = json_decode(file_get_contents('php://input'), true);
        $ip = $input['ip'] ?? '';
        if ($ip) {
            $bDb = new JsonDB('banned_ips');
            $bDb->insert(['ip' => $ip, 'banned_at' => date('Y-m-d H:i:s')]);
            $rDb = new JsonDB('requests');
            foreach ($rDb->getAll() as $id => $req) { if (($req['ip'] ?? '') === $ip) $rDb->delete($id); }
        }
        $response = ['status' => 'success'];
    }

    // Export dat do CSV
    if ($endpoint === 'export-csv' && $method === 'GET') {
        $type = $_GET['type'] ?? '';
        ob_clean();
        header('Content-Type: text/csv; charset=utf-8');
        // Přidání BOM pro Excel, aby správně otevřel UTF-8 CSV
        echo "\xEF\xBB\xBF";
        $output = fopen('php://output', 'w');
        
        if ($type === 'newsletter') {
            header('Content-Disposition: attachment; filename="odberatele.csv"');
            $db = new JsonDB('newsletter');
            fputcsv($output, ['E-mail', 'Datum registrace', 'Ověřeno'], ';');
            foreach ($db->getAll() as $row) {
                if (is_array($row)) fputcsv($output, [$row['email'] ?? '', $row['created_at'] ?? '', !empty($row['verified']) ? 'Ano' : 'Ne'], ';');
            }
        } elseif ($type === 'customers') {
            header('Content-Disposition: attachment; filename="zakaznici_a_obchodnici.csv"');
            $db = new JsonDB('customers');
            fputcsv($output, ['Jméno/Firma', 'Typ', 'E-mail', 'Telefon', 'Datum vytvoření'], ';');
            foreach ($db->getAll() as $row) {
                if (is_array($row)) {
                    $t = ($row['type'] ?? '') === 'sales' ? 'Obchodník' : 'Zákazník';
                    fputcsv($output, [$row['name'] ?? '', $t, $row['email'] ?? '', $row['phone'] ?? '', $row['created_at'] ?? ''], ';');
                }
            }
        }
        fclose($output);
        exit;
    }

    // Generování a odesílání PDF reportů
    if ($endpoint === 'campaign-report' && $method === 'POST') {
        $campId = $_POST['campId'] ?? '';
        $to = $_POST['to'] ?? '';
        $subject = $_POST['subject'] ?? '';
        $message = $_POST['message'] ?? '';
        
        $campsDb = new JsonDB('campaigns');
        $customersDb = new JsonDB('customers');
        $spacesDb = new JsonDB('ad_spaces');
        $settingsDb = new JsonDB('settings');
        
        $campaign = $campsDb->getById($campId);
        if (!$campaign) {
            $response = ['status' => 'error', 'message' => 'Kampaň nenalezena.'];
        } else {
            $customer = $customersDb->getById($campaign['customerId']);
            $space = $spacesDb->getById($campaign['spaceId']);
            
            $autoloadPath = __DIR__ . '/vendor/autoload.php';
            if (!file_exists($autoloadPath)) {
                echo json_encode(['status' => 'error', 'message' => 'Závislosti nejsou nainstalovány. Spusťte "composer install".']); exit;
            }
            require_once $autoloadPath;
            
            try {
                $yearlyDb = new JsonDB('stats_yearly');
                $stats = $yearlyDb->getAll();
                $campaignStats = [];
                $startTs = strtotime($campaign['start'] . ' 00:00:00');
                $endTs = strtotime($campaign['end'] . ' 23:59:59');
                foreach ($stats as $s) {
                    if (isset($s['hour'])) {
                        $ts = strtotime($s['hour']);
                        if ($ts >= $startTs && $ts <= $endTs) { $campaignStats[] = $s; }
                    }
                }
                usort($campaignStats, function($a, $b) { return strtotime($a['hour']) <=> strtotime($b['hour']); });

                $svgWidth = 600; $svgHeight = 250; $paddingX = 40; $paddingY = 30;
                if (count($campaignStats) > 1) {
                    $maxPeak = max(array_column($campaignStats, 'listeners_peak')); if ($maxPeak < 10) $maxPeak = 10;
                    $pointsAvg = []; $pointsPeak = []; $count = count($campaignStats);
                    $xStep = ($svgWidth - 2 * $paddingX) / ($count - 1);
                    foreach ($campaignStats as $i => $stat) {
                        $x = $paddingX + ($i * $xStep);
                        $yAvg = $svgHeight - $paddingY - (($stat['listeners_avg'] / $maxPeak) * ($svgHeight - 2 * $paddingY));
                        $yPeak = $svgHeight - $paddingY - (($stat['listeners_peak'] / $maxPeak) * ($svgHeight - 2 * $paddingY));
                        $pointsAvg[] = sprintf("%.1f,%.1f", $x, $yAvg); $pointsPeak[] = sprintf("%.1f,%.1f", $x, $yPeak);
                    }
                    $svg = '<svg width="'.$svgWidth.'" height="'.$svgHeight.'" viewBox="0 0 '.$svgWidth.' '.$svgHeight.'" xmlns="http://www.w3.org/2000/svg" style="font-family: sans-serif;">';
                    $svg .= '<rect width="100%" height="100%" fill="#ffffff" stroke="#eeeeee" stroke-width="1"/>';
                    $svg .= '<line x1="'.$paddingX.'" y1="'.($svgHeight-$paddingY).'" x2="'.($svgWidth-$paddingX).'" y2="'.($svgHeight-$paddingY).'" stroke="#cccccc" stroke-width="1"/>';
                    $svg .= '<line x1="'.$paddingX.'" y1="'.$paddingY.'" x2="'.$paddingX.'" y2="'.($svgHeight-$paddingY).'" stroke="#cccccc" stroke-width="1"/>';
                    for ($i = 0; $i <= 4; $i++) {
                        $y = $svgHeight - $paddingY - ($i * ($svgHeight - 2 * $paddingY) / 4); $val = round($i * $maxPeak / 4);
                        $svg .= '<line x1="'.$paddingX.'" y1="'.$y.'" x2="'.($svgWidth-$paddingX).'" y2="'.$y.'" stroke="#eeeeee" stroke-width="1"/>';
                        $svg .= '<text x="'.($paddingX - 5).'" y="'.($y + 4).'" font-size="10" fill="#666666" text-anchor="end">'.$val.'</text>';
                    }
                    $svg .= '<polyline points="'.implode(' ', $pointsAvg).'" fill="none" stroke="#f2c94c" stroke-width="2"/>';
                    $svg .= '<polyline points="'.implode(' ', $pointsPeak).'" fill="none" stroke="#ff4b2b" stroke-width="2" stroke-dasharray="5,5"/>';
                    $svg .= '</svg>';
                    $svgBase64 = 'data:image/svg+xml;base64,' . base64_encode($svg);
                    $chartHtml = "<h3 style='margin-top:30px;'>Graf výkonu poslechovosti během kampaně</h3><div style='margin-bottom:10px;'><img src='{$svgBase64}'></div><div style='font-size:12px;'><span style='color:#ff4b2b;'>- - -</span> Špička posluchačů (Peak) &nbsp;&nbsp;&nbsp; <span style='color:#f2c94c;'>——</span> Průměr posluchačů</div>";
                } else { $chartHtml = "<h3 style='margin-top:30px;'>Graf výkonu poslechovosti</h3><p><i>Pro zvolené období zatím není dostatek statistických dat k vykreslení grafu.</i></p>"; }

                $mpdf = new \Mpdf\Mpdf(['tempDir' => sys_get_temp_dir() . '/mpdf']);
                $html = "<h1>Report reklamní kampaně</h1><h2>Kampaň: " . htmlspecialchars($campaign['name']) . "</h2>";
                $html .= "<p><strong>Zákazník:</strong> " . htmlspecialchars($customer['name']) . " (" . htmlspecialchars($customer['email']) . ")</p>";
                $html .= "<p><strong>Reklamní prostor:</strong> " . htmlspecialchars($space['name']) . "</p>";
                $html .= "<p><strong>Smluvené období:</strong> {$campaign['start']} až {$campaign['end']}</p>";
                $html .= "<p><strong>Aktuální stav:</strong> " . ($campaign['active'] ? 'Aktivní' : 'Neaktivní/Ukončená') . "</p>";
                $html .= $chartHtml;
                $mpdf->WriteHTML($html);
                $pdfContent = $mpdf->Output('', \Mpdf\Output\Destination::STRING_RETURN);
                
                $mail = new \PHPMailer\PHPMailer\PHPMailer(true);
                $mail->CharSet = 'UTF-8';
                $mail->Timeout = 5;
                $mail->SMTPDebug = 0;
                
                $smtpConfig = null;
                foreach ($settingsDb->getAll() as $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'smtp') { $smtpConfig = $row['value']; } }
                
                if ($smtpConfig && !empty($smtpConfig['host'])) {
                    $mail->isSMTP();
                    $mail->Host = $smtpConfig['host'];
                    $mail->SMTPAuth = true;
                    $mail->Username = $smtpConfig['username'] ?? '';
                    $mail->Password = $smtpConfig['password'] ?? '';
                    $mail->SMTPSecure = $smtpConfig['encryption'] === 'tls' ? \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS : ($smtpConfig['encryption'] === 'ssl' ? \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS : '');
                    $mail->Port = (int)$smtpConfig['port'];
                }
                
                $fromEmail = !empty($smtpConfig['from_email']) ? $smtpConfig['from_email'] : 'info@radiowebsystem.local';
                $fromName = !empty($smtpConfig['from_name']) ? $smtpConfig['from_name'] : 'RadioWebSystem';
                
                $mail->setFrom($fromEmail, $fromName);
                
                global $currentUser;
                if ($currentUser && !empty($currentUser['username']) && filter_var($currentUser['username'], FILTER_VALIDATE_EMAIL)) {
                    $mail->addReplyTo($currentUser['username'], $currentUser['name'] ?? '');
                }
                
                if (empty($to)) throw new Exception("Příjemce nemá vyplněný e-mail.");
                $mail->addAddress($to);
                $mail->isHTML(true);
                $mail->Subject = $subject;
                $mail->Body = $message;
                $mail->addStringAttachment($pdfContent, "Report_Kampane_" . preg_replace('/[^a-zA-Z0-9_-]/', '_', $campaign['name']) . ".pdf");
                
                if (!empty($_FILES['attachments'])) {
                    $files = $_FILES['attachments'];
                    for ($i = 0; $i < count($files['name']); $i++) { if ($files['error'][$i] === UPLOAD_ERR_OK) { $mail->addAttachment($files['tmp_name'][$i], $files['name'][$i]); } }
                }
                
                $mail->send();
                
                $response = ['status' => 'success', 'message' => 'PDF report byl úspěšně vygenerován a odeslán zákazníkovi.'];
            } catch (\Throwable $e) {
                $response = ['status' => 'error', 'message' => 'Chyba: ' . $e->getMessage()];
            }
        }
    }

    // Odeslání kontaktního formuláře z frontendu
    if ($endpoint === 'contact') {
        $input = json_decode(file_get_contents('php://input'), true);
        if (!is_array($input)) $input = [];
        if (!verifyRecaptcha($input)) { echo json_encode(['status' => 'error', 'message' => 'Spam detekován (Ochrana).']); exit; }
        if (!empty($input['email']) && !empty($input['message'])) {
            $settingsDb = new JsonDB('settings');
            $autoloadPath = __DIR__ . '/vendor/autoload.php';
            if (file_exists($autoloadPath)) {
                require_once $autoloadPath;
                try {
                    $mail = new \PHPMailer\PHPMailer\PHPMailer(true);
                    $mail->CharSet = 'UTF-8';
                        $mail->Timeout = 5;
                        $mail->SMTPDebug = 0;
                    $smtpConfig = null;
                    $tpl = ['color_accent' => '#00d2ff', 'color_bg1' => '#1e3c72', 'color_bg2' => '#2a5298'];
                    foreach ($settingsDb->getAll() as $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'smtp') { $smtpConfig = $row['value']; break; } }
                    foreach ($settingsDb->getAll() as $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'template' && is_array($row['value'])) { $tpl = array_merge($tpl, $row['value']); break; } }
                    if ($smtpConfig && !empty($smtpConfig['host'])) {
                        $mail->isSMTP(); $mail->Host = $smtpConfig['host']; $mail->SMTPAuth = true;
                        $mail->Username = $smtpConfig['username'] ?? ''; $mail->Password = $smtpConfig['password'] ?? '';
                        $mail->SMTPSecure = $smtpConfig['encryption'] === 'tls' ? \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS : ($smtpConfig['encryption'] === 'ssl' ? \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS : '');
                        $mail->Port = (int)$smtpConfig['port'];
                    }
                    $fromEmail = !empty($smtpConfig['from_email']) ? $smtpConfig['from_email'] : 'info@radiowebsystem.local';
                    $fromName = !empty($smtpConfig['from_name']) ? $smtpConfig['from_name'] : 'RadioWebSystem';
                    
                    $mail->setFrom($fromEmail, $fromName);
                    $mail->addAddress($fromEmail);
                    $mail->addReplyTo($input['email'], $input['name'] ?? 'Posluchač');
                    $mail->isHTML(true);
                    $mail->Subject = "Zpráva z webu od: " . htmlspecialchars($input['name'] ?? 'Posluchač');
                    $mail->Body = "<div style='font-family: sans-serif; max-width: 600px; margin: 0 auto; background: linear-gradient(135deg, {$tpl['color_bg1']} 0%, {$tpl['color_bg2']} 100%); padding: 20px; border-radius: 15px; color: #fff;'><div style='background: rgba(255,255,255,0.1); padding: 20px; border-radius: 10px; border: 1px solid rgba(255,255,255,0.2); text-align: left;'><h2 style='color: {$tpl['color_accent']}; margin-top: 0;'>✉️ Nová zpráva z kontaktního formuláře</h2><p><strong>Od:</strong> ".htmlspecialchars($input['name'] ?? 'Neuvedeno')." (".htmlspecialchars($input['email']).")</p><p><strong>Zpráva:</strong><br>".nl2br(htmlspecialchars($input['message']))."</p></div></div>";
                    $mail->send();
                    $response = ['status' => 'success', 'message' => 'Zpráva odeslána.'];
                } catch (\Throwable $e) { $response = ['status' => 'error', 'message' => 'Chyba SMTP: ' . $e->getMessage()]; }
            } else { $response = ['status' => 'error', 'message' => 'Není nainstalován PHPMailer.']; }
        } else { $response = ['status' => 'error', 'message' => 'Chybí povinné údaje.']; }
    }

    // API endpoint pro test SMTP
    if ($endpoint === 'smtp-test') {
        $input = json_decode(file_get_contents('php://input'), true);
        if (!is_array($input)) $input = [];
        $smtpConfig = $input['smtp'] ?? null;
        if (!$smtpConfig || empty($smtpConfig['host'])) {
            $response = ['status' => 'error', 'message' => 'Vyplňte nejprve SMTP server (Host).'];
        } else {
            $autoloadPath = __DIR__ . '/vendor/autoload.php';
            if (!file_exists($autoloadPath)) {
                $response = ['status' => 'error', 'message' => 'Nenainstalován composer (PHPMailer).'];
            } else {
                require_once $autoloadPath;
                try {
                    $mail = new \PHPMailer\PHPMailer\PHPMailer(true);
                    $mail->CharSet = 'UTF-8';
                        $mail->Timeout = 5;
                        $mail->SMTPDebug = 0;
                    $mail->isSMTP();
                    $mail->Host = $smtpConfig['host'];
                    $mail->SMTPAuth = true;
                    $mail->Username = $smtpConfig['username'] ?? '';
                    $mail->Password = $smtpConfig['password'] ?? '';
                    $mail->SMTPSecure = $smtpConfig['encryption'] === 'tls' ? \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS : ($smtpConfig['encryption'] === 'ssl' ? \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS : '');
                    $mail->Port = (int)$smtpConfig['port'];
                    
                    $fromEmail = !empty($smtpConfig['from_email']) ? $smtpConfig['from_email'] : 'info@radiowebsystem.local';
                    $fromName = !empty($smtpConfig['from_name']) ? $smtpConfig['from_name'] : 'RadioWebSystem';
                    
                    $mail->setFrom($fromEmail, $fromName);
                    $mail->addAddress($fromEmail);
                    $mail->Subject = "Test spojení RadioWebSystem";
                    
                    $settingsDb = new JsonDB('settings');
                    $tpl = ['color_accent' => '#00d2ff', 'color_bg1' => '#1e3c72', 'color_bg2' => '#2a5298'];
                    $signature = '';
                    foreach ($settingsDb->getAll() as $row) { 
                        if (is_array($row) && isset($row['key']) && $row['key'] === 'template' && is_array($row['value'])) { $tpl = array_merge($tpl, $row['value']); } 
                        if (is_array($row) && isset($row['key']) && $row['key'] === 'email_signature') { $signature = $row['value']; }
                    }
                    $sigHtml = $signature ? "<br><br>" . $signature : "";
                    $msgHtml = "<div style='font-family: sans-serif; max-width: 600px; margin: 0 auto; background: linear-gradient(135deg, {$tpl['color_bg1']} 0%, {$tpl['color_bg2']} 100%); padding: 20px; border-radius: 15px; color: #fff;'><div style='background: rgba(255,255,255,0.1); padding: 20px; border-radius: 10px; border: 1px solid rgba(255,255,255,0.2); text-align: left;'><h2 style='color: {$tpl['color_accent']}; margin-top: 0;'>Test spojení SMTP</h2><p>Toto je testovací zpráva pro ověření funkčnosti SMTP odesílání.</p>{$sigHtml}</div></div>";
                    
                    $mail->isHTML(true);
                    $mail->Body = $msgHtml;
                    $mail->send();
                    $response = ['status' => 'success', 'message' => 'Testovací e-mail byl úspěšně odeslán na adresu odesílatele!'];
                } catch (\Throwable $e) {
                    $response = ['status' => 'error', 'message' => 'Chyba SMTP: ' . $e->getMessage()];
                }
            }
        }
    }

    // Licenční API Check
    if ($endpoint === 'license-check' && $method === 'GET') {
        $settingsDb = new JsonDB('settings');
        $apiKey = '';
        $targetLicId = null;
        foreach ($settingsDb->getAll() as $id => $row) {
            if (is_array($row) && isset($row['key']) && $row['key'] === 'rws_api_key') { $apiKey = $row['value']; }
            if (is_array($row) && isset($row['key']) && $row['key'] === 'license_info') { $targetLicId = $id; }
        }
        if (empty($apiKey)) {
            echo json_encode(['status' => 'success', 'data' => ['configured' => false]]); exit;
        }
        
        $url = "https://api.mysoft.cz/check.php?program=radiowebsystem&API=" . urlencode($apiKey);
        $ctx = stream_context_create(['http' => ['timeout' => 5]]);
        $res = @file_get_contents($url, false, $ctx);
        if ($res) {
            $lines = explode("\n", $res);
            $ini = [];
            foreach ($lines as $line) {
                $parts = explode('=', trim($line), 2);
                if (count($parts) === 2) { $ini[$parts[0]] = $parts[1]; }
            }
            $licData = ['configured' => true, 'api_key' => $apiKey, 'license' => $ini['Licence'] ?? 'Neznámá', 'valid_until' => $ini['DatumDo'] ?? '-'];
            $dbData = ['key' => 'license_info', 'value' => $licData];
            $targetLicId ? $settingsDb->update($targetLicId, $dbData) : $settingsDb->insert($dbData);
            
            $licData['local_version'] = RWS_VERSION;
            $licData['remote_version'] = $ini['Verze'] ?? RWS_VERSION;
            $licData['update_available'] = version_compare($licData['remote_version'], RWS_VERSION, '>');
            
            echo json_encode(['status' => 'success', 'data' => $licData]);
        } else {
            echo json_encode(['status' => 'error', 'message' => 'Chyba při komunikaci s licenčním serverem.']);
        }
        exit;
    }

    // API endpoint pro Historii songů
    if ($endpoint === 'songs') {
        $db = new JsonDB('songs');
        $method = $_SERVER['REQUEST_METHOD'];
        if ($method === 'GET') {
            $songs = array_values($db->getAll());
            $ignoredDb = new JsonDB('ignored_songs');
            $ignoredList = [];
            foreach ($ignoredDb->getAll() as $ig) { if (!empty($ig['name'])) $ignoredList[] = $ig['name']; }
            foreach ($songs as &$s) {
                if (is_array($s)) {
                    $name = trim($s['artist'] ?? '') . ' - ' . trim($s['title'] ?? '');
                    if (in_array($name, $ignoredList)) $s['excluded'] = true;
                }
            }
            usort($songs, function($a, $b) { return strtotime($b['played_at'] ?? '0') <=> strtotime($a['played_at'] ?? '0'); });
            $response = ['status' => 'success', 'data' => $songs];
        } elseif ($method === 'POST') {
            $input = json_decode(file_get_contents('php://input'), true);
            if (!is_array($input)) $input = [];
            
            if (isset($input['action']) && $input['action'] === 'toggle_exclude' && isset($input['id'])) {
                $song = $db->getById($input['id']);
                if ($song) {
                $ignoredDb = new JsonDB('ignored_songs');
                $name = trim($song['artist'] ?? '') . ' - ' . trim($song['title'] ?? '');
                $foundId = null;
                foreach ($ignoredDb->getAll() as $id => $ig) { if (($ig['name'] ?? '') === $name) { $foundId = $id; break; } }
                if ($foundId) {
                    $ignoredDb->delete($foundId);
                } else {
                    $ignoredDb->insert(['name' => $name]);
                }
                    $response = ['status' => 'success', 'message' => 'Stav hitparády upraven.'];
                } else {
                    $response = ['status' => 'error', 'message' => 'Song nenalezen.'];
                }
            } else if (!empty($input['artist']) && !empty($input['title'])) {
                $input['played_at'] = date('Y-m-d H:i:s');
                $db->insert($input);
                $response = ['status' => 'success', 'message' => 'Song zaznamenán.'];
            }
        }
    }

    // API pro Vzhled, Šablony a Menu
    if ($endpoint === 'template-config') {
        $db = new JsonDB('settings');
        $method = $_SERVER['REQUEST_METHOD'];
        if ($method === 'GET') {
            $tpl = ['header' => '', 'footer' => '', 'color_bg1' => '#1e3c72', 'color_bg2' => '#2a5298', 'color_accent' => '#00d2ff', 'font_family' => "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif", 'bg_image' => '', 'bg_repeat' => 'cover', 'site_title' => '', 'logo_image' => '', 'logo_size' => '100px', 'logo_position' => 'center', 'title_size' => '2rem', 'title_position' => 'center', 'social_fb' => '', 'social_ig' => ''];
            foreach ($db->getAll() as $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'template' && is_array($row['value'])) { $tpl = array_merge($tpl, $row['value']); break; } }
            $response = ['status' => 'success', 'data' => $tpl];
        } elseif ($method === 'POST') {
            $input = json_decode(file_get_contents('php://input'), true);
            $targetId = null;
            $existing = ['header' => '', 'footer' => '', 'color_bg1' => '#1e3c72', 'color_bg2' => '#2a5298', 'color_accent' => '#00d2ff', 'font_family' => "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif", 'bg_image' => '', 'bg_repeat' => 'cover', 'site_title' => '', 'logo_image' => '', 'logo_size' => '100px', 'logo_position' => 'center', 'title_size' => '2rem', 'title_position' => 'center', 'social_fb' => '', 'social_ig' => ''];
            foreach ($db->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'template') { $targetId = $id; if (is_array($row['value'])) { $existing = array_merge($existing, $row['value']); } break; } }
            
            if (isset($input['bg_image_base64'])) {
                if (!empty($input['bg_image_base64']) && strpos($input['bg_image_base64'], 'data:image') === 0) {
                    $mediaDir = __DIR__ . '/media';
                    if (!file_exists($mediaDir)) mkdir($mediaDir, 0777, true);
                    list($type, $data) = explode(';', $input['bg_image_base64']);
                    list(, $data)      = explode(',', $data);
                    $data = base64_decode($data);
                    $ext = strpos($type, 'png') !== false ? 'png' : (strpos($type, 'webp') !== false ? 'webp' : 'jpg');
                    $filename = 'bg_' . uniqid() . '.' . $ext;
                    file_put_contents($mediaDir . '/' . $filename, $data);
                    $input['bg_image'] = 'media/' . $filename;
                }
                unset($input['bg_image_base64']);
            } else {
                if (isset($existing['bg_image']) && !isset($input['bg_image_delete'])) $input['bg_image'] = $existing['bg_image'];
            }
            if (isset($input['bg_image_delete'])) { $input['bg_image'] = ''; unset($input['bg_image_delete']); }
            
            if (isset($input['logo_image_base64'])) {
                if (!empty($input['logo_image_base64']) && strpos($input['logo_image_base64'], 'data:image') === 0) {
                    $mediaDir = __DIR__ . '/media';
                    if (!file_exists($mediaDir)) mkdir($mediaDir, 0777, true);
                    list($type, $data) = explode(';', $input['logo_image_base64']);
                    list(, $data)      = explode(',', $data);
                    $data = base64_decode($data);
                    $ext = strpos($type, 'png') !== false ? 'png' : (strpos($type, 'webp') !== false ? 'webp' : 'jpg');
                    $filename = 'logo_' . uniqid() . '.' . $ext;
                    file_put_contents($mediaDir . '/' . $filename, $data);
                    $input['logo_image'] = 'media/' . $filename;
                }
                unset($input['logo_image_base64']);
            } else {
                if (isset($existing['logo_image']) && !isset($input['logo_image_delete'])) $input['logo_image'] = $existing['logo_image'];
            }
            if (isset($input['logo_image_delete'])) { $input['logo_image'] = ''; unset($input['logo_image_delete']); }

            $mergedData = array_merge($existing, $input);
            $data = ['key' => 'template', 'value' => $mergedData];
            $targetId ? $db->update($targetId, $data) : $db->insert($data);
            logActivity('Úprava vzhledu webu', 'Změna parametrů šablony');
            $response = ['status' => 'success', 'message' => 'Vzhled uložen.'];
        }
    }

    if ($endpoint === 'boxes') {
        $db = new JsonDB('boxes');
        $method = $_SERVER['REQUEST_METHOD'];
        if ($method === 'GET') {
            $all = $db->getAll();
            $hasOnAir = false; $hasNowPlaying = false; $hasContact = false;
            foreach ($all as $b) {
                if (isset($b['system_type']) && $b['system_type'] === 'onair') $hasOnAir = true;
                if (isset($b['system_type']) && $b['system_type'] === 'nowplaying') $hasNowPlaying = true;
                if (isset($b['system_type']) && $b['system_type'] === 'contact') $hasContact = true;
                if (is_array($b) && isset($b['system_type']) && $b['system_type'] === 'queue') $hasQueue = true;
                if (is_array($b) && isset($b['system_type']) && $b['system_type'] === 'weather') $hasWeather = true;
            }
            if (!$hasOnAir) $db->insert(['title' => '📻 ON-AIR', 'content' => '', 'position' => 'left', 'order' => 1, 'is_system' => true, 'system_type' => 'onair']);
            if (!$hasNowPlaying) $db->insert(['title' => '🎵 Právě vysíláme', 'content' => '', 'position' => 'right', 'order' => 1, 'is_system' => true, 'system_type' => 'nowplaying']);
            if (!$hasContact) $db->insert(['title' => '✉️ Napište nám', 'content' => '', 'position' => 'right', 'order' => 2, 'is_system' => true, 'system_type' => 'contact']);
            if (!isset($hasQueue) || !$hasQueue) $db->insert(['title' => '🔜 Budeme hrát', 'content' => '', 'position' => 'right', 'order' => 3, 'is_system' => true, 'system_type' => 'queue']);
            if (!isset($hasWeather) || !$hasWeather) $db->insert(['title' => '⛅ Počasí', 'content' => 'Praha', 'position' => 'left', 'order' => 4, 'is_system' => true, 'system_type' => 'weather']);
            $all = array_values($db->getAll());
            usort($all, function($a, $b) { return (int)($a['order'] ?? 0) <=> (int)($b['order'] ?? 0); });
            $response = ['status' => 'success', 'data' => $all];
        } elseif ($method === 'POST') {
            $input = json_decode(file_get_contents('php://input'), true);
            if (!is_array($input)) $input = [];
            if (isset($input['id']) && !empty($input['id'])) { $id = $input['id']; unset($input['id']); $db->update($id, $input); } 
            else { unset($input['id']); $db->insert($input); }
            logActivity('Změna Boxu', $input['title'] ?? '');
            $response = ['status' => 'success', 'message' => 'Box uložen.'];
        } elseif ($method === 'DELETE') {
            $input = json_decode(file_get_contents('php://input'), true);
            if (!is_array($input)) $input = [];
            if (isset($input['id'])) {
                $box = $db->getById($input['id']);
                if ($box && empty($box['is_system'])) { $db->delete($input['id']); logActivity('Smazán Box', $box['title'] ?? ''); $response = ['status' => 'success']; } 
                else { $response = ['status' => 'error', 'message' => 'Systémový box nelze smazat.']; }
            }
        }
    }

    // API endpoint pro Nastavení systému
    if ($endpoint === 'settings-config') {
        $db = new JsonDB('settings');
        $method = $_SERVER['REQUEST_METHOD'];
        if ($method === 'GET') {
            $smtp = null; $icecast_url = ''; $stream_url = ''; $now_playing = ''; $now_playing_artwork = ''; $stream_type = 'icecast2'; $tinymce_api_key = ''; $streams = []; $recaptcha_site_key = ''; $recaptcha_secret_key = ''; $openai_api_key = ''; $gemini_api_key = ''; $active_langs = null; $webhook_token = ''; $ai_provider = 'openai'; $gemini_model = 'gemini-2.5-flash'; $rws_api_key = ''; $email_signature = '';
            foreach ($db->getAll() as $row) {
                if (!is_array($row)) continue;
                if (isset($row['key']) && $row['key'] === 'smtp') { $smtp = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'icecast_url') { $icecast_url = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'stream_url') { $stream_url = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'now_playing') { $now_playing = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'now_playing_artwork') { $now_playing_artwork = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'stream_type') { $stream_type = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'tinymce_api_key') { $tinymce_api_key = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'streams') { $streams = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'recaptcha_site_key') { $recaptcha_site_key = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'recaptcha_secret_key') { $recaptcha_secret_key = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'openai_api_key') { $openai_api_key = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'gemini_api_key') { $gemini_api_key = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'active_langs') { $active_langs = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'webhook_token') { $webhook_token = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'ai_provider') { $ai_provider = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'gemini_model') { $gemini_model = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'rws_api_key') { $rws_api_key = $row['value']; }
                if (isset($row['key']) && $row['key'] === 'email_signature') { $email_signature = $row['value']; }
            }
            if (!isset($active_langs) || !is_array($active_langs)) $active_langs = array_keys($sysLangsAll);
            $response = ['status' => 'success', 'data' => ['smtp' => $smtp, 'icecast_url' => $icecast_url, 'stream_url' => $stream_url, 'now_playing' => $now_playing, 'now_playing_artwork' => $now_playing_artwork, 'stream_type' => $stream_type, 'tinymce_api_key' => $tinymce_api_key, 'streams' => $streams, 'recaptcha_site_key' => $recaptcha_site_key, 'recaptcha_secret_key' => $recaptcha_secret_key, 'openai_api_key' => $openai_api_key, 'gemini_api_key' => $gemini_api_key, 'active_langs' => $active_langs, 'webhook_token' => $webhook_token, 'ai_provider' => $ai_provider, 'gemini_model' => $gemini_model, 'rws_api_key' => $rws_api_key, 'email_signature' => $email_signature]];
        } elseif ($method === 'POST') {
            $input = json_decode(file_get_contents('php://input'), true);
            if (isset($input['smtp'])) {
                $targetId = null; foreach ($db->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'smtp') { $targetId = $id; break; } }
                $data = ['key' => 'smtp', 'value' => $input['smtp']];
                $targetId ? $db->update($targetId, $data) : $db->insert($data);
            }
            if (isset($input['icecast_url'])) {
                $targetId = null; foreach ($db->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'icecast_url') { $targetId = $id; break; } }
                $data = ['key' => 'icecast_url', 'value' => $input['icecast_url']];
                $targetId ? $db->update($targetId, $data) : $db->insert($data);
            }
            if (isset($input['stream_url'])) {
                $targetId = null; foreach ($db->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'stream_url') { $targetId = $id; break; } }
                $data = ['key' => 'stream_url', 'value' => $input['stream_url']];
                $targetId ? $db->update($targetId, $data) : $db->insert($data);
            }
            if (isset($input['stream_type'])) {
                $targetId = null; foreach ($db->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'stream_type') { $targetId = $id; break; } }
                $data = ['key' => 'stream_type', 'value' => $input['stream_type']];
                $targetId ? $db->update($targetId, $data) : $db->insert($data);
            }
            if (isset($input['tinymce_api_key'])) {
                $targetId = null; foreach ($db->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'tinymce_api_key') { $targetId = $id; break; } }
                $data = ['key' => 'tinymce_api_key', 'value' => $input['tinymce_api_key']];
                $targetId ? $db->update($targetId, $data) : $db->insert($data);
            }
            if (isset($input['webhook_token'])) {
                $targetId = null; foreach ($db->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'webhook_token') { $targetId = $id; break; } }
                $data = ['key' => 'webhook_token', 'value' => $input['webhook_token']];
                $targetId ? $db->update($targetId, $data) : $db->insert($data);
            }
            if (isset($input['streams'])) {
                $targetId = null; foreach ($db->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'streams') { $targetId = $id; break; } }
                $data = ['key' => 'streams', 'value' => $input['streams']];
                $targetId ? $db->update($targetId, $data) : $db->insert($data);
            }
            foreach (['recaptcha_site_key', 'recaptcha_secret_key', 'openai_api_key', 'gemini_api_key', 'ai_provider', 'gemini_model', 'rws_api_key'] as $k) {
                if (isset($input[$k])) {
                    $targetId = null; foreach ($db->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === $k) { $targetId = $id; break; } }
                    $data = ['key' => $k, 'value' => $input[$k]]; $targetId ? $db->update($targetId, $data) : $db->insert($data);
                }
            }
            if (isset($input['active_langs']) && is_array($input['active_langs'])) {
                $targetId = null; foreach ($db->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'active_langs') { $targetId = $id; break; } }
                $data = ['key' => 'active_langs', 'value' => $input['active_langs']]; $targetId ? $db->update($targetId, $data) : $db->insert($data);
            }
            if (isset($input['email_signature'])) {
                $targetId = null; foreach ($db->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'email_signature') { $targetId = $id; break; } }
                $data = ['key' => 'email_signature', 'value' => $input['email_signature']]; $targetId ? $db->update($targetId, $data) : $db->insert($data);
            }
            logActivity('Změna nastavení systému', 'Konfigurace aktualizována');
            $response = ['status' => 'success', 'message' => 'Nastavení uloženo.'];
        }
    }

    // API Webhook Endpoint pro studiový software
    if ($endpoint === 'webhook' && $method === 'POST') {
        $input = json_decode(file_get_contents('php://input'), true);
        if (!is_array($input)) $input = [];
        $settingsDb = new JsonDB('settings');
        $validToken = '';
        foreach ($settingsDb->getAll() as $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'webhook_token') { $validToken = $row['value']; break; } }
        $providedToken = str_replace('Bearer ', '', $input['token'] ?? ($_SERVER['HTTP_AUTHORIZATION'] ?? ''));
        if (empty($validToken) || $providedToken !== $validToken) { $response = ['status' => 'error', 'message' => 'Neplatný token.']; } else {
            $action = $input['action'] ?? '';
            if ($action === 'now_playing') {
                $artist = trim($input['artist'] ?? ''); $title = trim($input['title'] ?? '');
                if ($artist && $title) {
                    $nowPlaying = $artist . ' - ' . $title;
                    $targetNpId = null; foreach ($settingsDb->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'now_playing') { $targetNpId = $id; break; } }
                    $npData = ['key' => 'now_playing', 'value' => $nowPlaying]; $targetNpId ? $settingsDb->update($targetNpId, $npData) : $settingsDb->insert($npData);
                    $songsDb = new JsonDB('songs'); $songsDb->insert(['artist' => $artist, 'title' => $title, 'played_at' => date('Y-m-d H:i:s')]);
                }
                $response = ['status' => 'success'];
            } elseif ($action === 'queue') {
                $queue = $input['songs'] ?? [];
                $targetQId = null; foreach ($settingsDb->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'upcoming_queue') { $targetQId = $id; break; } }
                $qData = ['key' => 'upcoming_queue', 'value' => $queue]; $targetQId ? $settingsDb->update($targetQId, $qData) : $settingsDb->insert($qData);
                $response = ['status' => 'success'];
            } elseif ($action === 'set_moderator') {
                $modId = $input['moderator_id'] ?? '';
                $targetOverrideId = null; foreach ($settingsDb->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'onair_override') { $targetOverrideId = $id; break; } }
                if (empty($modId)) { if ($targetOverrideId) $settingsDb->delete($targetOverrideId); } else {
                    $validUntil = strtotime(date('Y-m-d H:00:00', strtotime('+1 hour')));
                    $data = ['key' => 'onair_override', 'value' => ['moderator_ids' => [$modId]], 'valid_until' => $validUntil];
                    $targetOverrideId ? $settingsDb->update($targetOverrideId, $data) : $settingsDb->insert($data);
                }
                $response = ['status' => 'success'];
            } else { $response = ['status' => 'error', 'message' => 'Neznámá akce.']; }
        }
    }

    // API pro uložení ceníku a jeho PDF export
    if ($endpoint === 'ad-settings') {
        $db = new JsonDB('settings');
        if ($method === 'GET') {
            $html = '';
            foreach ($db->getAll() as $row) {
                if (is_array($row) && isset($row['key']) && $row['key'] === 'pricelist_html') { $html = $row['value']; break; }
            }
            $response = ['status' => 'success', 'data' => ['pricelist_html' => $html]];
        } elseif ($method === 'POST') {
            $input = json_decode(file_get_contents('php://input'), true);
            if (isset($input['pricelist_html'])) {
                $targetId = null;
                foreach ($db->getAll() as $id => $row) {
                    if (is_array($row) && isset($row['key']) && $row['key'] === 'pricelist_html') { $targetId = $id; break; }
                }
                $data = ['key' => 'pricelist_html', 'value' => $input['pricelist_html']];
                $targetId ? $db->update($targetId, $data) : $db->insert($data);
                logActivity('Úprava ceníku', 'Ceník byl aktualizován');
                $response = ['status' => 'success', 'message' => 'Ceník uložen.'];
            }
        }
    }

    if ($endpoint === 'pricelist-pdf' && $method === 'GET') {
        if (!$currentUser) { header('HTTP/1.1 401 Unauthorized'); exit('Unauthorized'); }
        $db = new JsonDB('settings');
        $htmlContent = '';
        foreach ($db->getAll() as $row) {
            if (is_array($row) && isset($row['key']) && $row['key'] === 'pricelist_html') { $htmlContent = $row['value']; break; }
        }
        $autoloadPath = __DIR__ . '/vendor/autoload.php';
        if (!file_exists($autoloadPath)) { die('Závislosti nejsou nainstalovány. Spusťte "composer install".'); }
        require_once $autoloadPath;
        try {
            $mpdf = new \Mpdf\Mpdf(['tempDir' => sys_get_temp_dir() . '/mpdf']);
            $mpdf->WriteHTML("<h1>Ceník reklamy a služeb</h1>" . $htmlContent);
            $mpdf->Output('Cenik_Reklamy.pdf', \Mpdf\Output\Destination::INLINE); exit;
        } catch (\Throwable $e) { die('Chyba při generování PDF: ' . $e->getMessage()); }
    }

    // API endpoint pro editaci systémových chybových stránek (ISPConfig)
    if ($endpoint === 'system-files') {
        $allowedFiles = ['400.html', '401.html', '404.html', '405.html', '500.html', '502.html', '503.html']; // Whitelist
        $file = $_GET['file'] ?? '';
        if (!in_array($file, $allowedFiles)) {
            $response = ['status' => 'error', 'message' => 'Přístup k tomuto souboru je zakázán.'];
        } else {
            $errorDir = __DIR__ . '/error';
            if (!is_dir($errorDir)) { @mkdir($errorDir, 0777, true); }
            $filePath = $errorDir . '/' . $file;
            if ($method === 'GET') {
                $content = file_exists($filePath) ? file_get_contents($filePath) : '';
                $response = ['status' => 'success', 'data' => ['content' => $content]];
            } elseif ($method === 'POST') {
                $input = json_decode(file_get_contents('php://input'), true);
                if (isset($input['content'])) {
                    file_put_contents($filePath, $input['content']);
                    logActivity('Upravena chybová stránka', 'error/' . $file);
                    $response = ['status' => 'success', 'message' => 'Soubor uložen.'];
                }
            }
        }
    }

    // API endpoint pro Systémový Log (Activity Log)
    if ($endpoint === 'activity_log') {
        $db = new JsonDB('activity_log');
        if ($method === 'GET') {
            $logs = array_values($db->getAll());
            usort($logs, function($a, $b) { $tA = is_array($a) && isset($a['created_at']) ? strtotime($a['created_at']) : 0; $tB = is_array($b) && isset($b['created_at']) ? strtotime($b['created_at']) : 0; return $tB <=> $tA; });
            $response = ['status' => 'success', 'data' => $logs];
        }
    }

    // API pro Statistiky
    if ($endpoint === 'stats') {
        $db = new JsonDB('stats');
        $all = array_values($db->getAll());
        usort($all, function($a, $b) { $tA = is_array($a) && isset($a['timestamp']) ? strtotime($a['timestamp']) : 0; $tB = is_array($b) && isset($b['timestamp']) ? strtotime($b['timestamp']) : 0; return $tA <=> $tB; });
        $response = ['status' => 'success', 'data' => $all];
    }

    if ($endpoint === 'stats-yearly') {
        $db = new JsonDB('stats_yearly');
        $all = array_values($db->getAll());
        usort($all, function($a, $b) { $tA = is_array($a) && isset($a['hour']) ? strtotime($a['hour']) : 0; $tB = is_array($b) && isset($b['hour']) ? strtotime($b['hour']) : 0; return $tA <=> $tB; });
        $response = ['status' => 'success', 'data' => $all];
    }

    if ($endpoint === 'stats-web') {
        $db = new JsonDB('web_stats');
        $all = array_values($db->getAll());
        usort($all, function($a, $b) { $tA = is_array($a) && isset($a['hour']) ? strtotime($a['hour']) : 0; $tB = is_array($b) && isset($b['hour']) ? strtotime($b['hour']) : 0; return $tA <=> $tB; });
        $response = ['status' => 'success', 'data' => $all];
    }

    if ($endpoint === 'stats-sync') {
        $settingsDb = new JsonDB('settings');
        $statsDb = new JsonDB('stats');
        $icecastUrl = '';
        $streamType = 'icecast2';
        $streamUrl = '';
        foreach ($settingsDb->getAll() as $row) { 
            if (is_array($row) && isset($row['key']) && $row['key'] === 'icecast_url') { $icecastUrl = $row['value']; }
            if (is_array($row) && isset($row['key']) && $row['key'] === 'stream_type') { $streamType = $row['value']; }
            if (is_array($row) && isset($row['key']) && $row['key'] === 'stream_url') { $streamUrl = $row['value']; }
        }
        $listeners = 0; $nowPlaying = '';
        if (!empty($icecastUrl)) {
            $ctx = stream_context_create([
                'http' => ['timeout' => 3, 'ignore_errors' => true, 'user_agent' => 'Mozilla/5.0 (compatible; RadioWebSystem/Sync)'],
                'ssl' => ['verify_peer' => false, 'verify_peer_name' => false]
            ]);
            $json = @file_get_contents($icecastUrl, false, $ctx);
            if ($json && $data = json_decode($json, true)) {
                if ($streamType === 'shoutcast2') {
                    $listeners = isset($data['currentlisteners']) ? (int)$data['currentlisteners'] : 0;
                    $nowPlaying = isset($data['songtitle']) ? $data['songtitle'] : '';
                } else {
                    if (isset($data['icestats']['source'])) {
                        $src = $data['icestats']['source'];
                        $mounts = is_array($src) && isset($src[0]) ? $src : [$src];
                        $matchedMount = null;
                        $streamPath = '';
                        if (!empty($streamUrl)) {
                            $parsed = parse_url($streamUrl, PHP_URL_PATH);
                            if ($parsed && $parsed !== '/') $streamPath = $parsed;
                        }
                        if (!empty($streamPath)) {
                            foreach($mounts as $mount) { 
                                $listenUrl = isset($mount['listenurl']) ? $mount['listenurl'] : '';
                                if (strpos($listenUrl, $streamPath) !== false) { $matchedMount = $mount; break; }
                            }
                        }
                        if (!$matchedMount && count($mounts) > 0) $matchedMount = $mounts[0];
                        if ($matchedMount) {
                            if(isset($matchedMount['listeners'])) $listeners = (int)$matchedMount['listeners']; 
                            if(isset($matchedMount['title'])) $nowPlaying = $matchedMount['title']; 
                            elseif(isset($matchedMount['server_name'])) $nowPlaying = $matchedMount['server_name'];
                        }
                    }
                }
            }
        } else { $listeners = 0; $nowPlaying = ''; }
        
        if (!empty($nowPlaying)) {
            $nowPlaying = preg_replace('/\.(mp3|wav|ogg|m4a|aac|flac|wma)$/i', '', $nowPlaying);
            $nowPlaying = preg_replace('/\s*-\s*/', ' - ', $nowPlaying);
        }
        
        $statsDb->insert(['timestamp' => date('Y-m-d H:i:s'), 'listeners' => $listeners]);
        $all = $statsDb->getAll();
        if (count($all) > 50) {
            uasort($all, function($a, $b) { return strtotime($a['timestamp']) <=> strtotime($b['timestamp']); });
            foreach(array_slice(array_keys($all), 0, count($all) - 50) as $id) { $statsDb->delete($id); }
        }
        
        $targetNpId = null; foreach ($settingsDb->getAll() as $id => $row) { if (is_array($row) && isset($row['key']) && $row['key'] === 'now_playing') { $targetNpId = $id; break; } }
        $npData = ['key' => 'now_playing', 'value' => $nowPlaying];
        $targetNpId ? $settingsDb->update($targetNpId, $npData) : $settingsDb->insert($npData);
        
        if (!empty($nowPlaying)) {
            $songsDb = new JsonDB('songs');
            $allSongs = array_values($songsDb->getAll());
            usort($allSongs, function($a, $b) { $tA = is_array($a) && isset($a['played_at']) ? strtotime($a['played_at']) : 0; $tB = is_array($b) && isset($b['played_at']) ? strtotime($b['played_at']) : 0; return $tB <=> $tA; });
            $lastSong = !empty($allSongs) ? $allSongs[0] : null;
            $parts = explode(' - ', $nowPlaying, 2);
            $artist = trim($parts[0]);
            $title = isset($parts[1]) ? trim($parts[1]) : 'Neznámý název';
            $isDifferent = true;
            if ($lastSong) {
                $lastFullName = $lastSong['artist'] . ' - ' . $lastSong['title'];
                if ($lastFullName === $artist . ' - ' . $title || $lastFullName === $nowPlaying) { $isDifferent = false; }
            }
            if ($isDifferent) {
                $artworkUrl = '';
                $term = urlencode($artist . ' ' . $title);
                $itunesJson = @file_get_contents("https://itunes.apple.com/search?term={$term}&entity=song&limit=1&country=cz");
                if ($itunesJson && $itunesData = json_decode($itunesJson, true)) {
                    $artworkUrl = $itunesData['results'][0]['artworkUrl100'] ?? '';
                }
                $songsDb->insert(['artist' => $artist, 'title' => $title, 'played_at' => date('Y-m-d H:i:s'), 'artwork' => $artworkUrl]);
                $targetArtId = null; foreach ($settingsDb->getAll() as $id => $row) { if (isset($row['key']) && $row['key'] === 'now_playing_artwork') { $targetArtId = $id; break; } }
                $artData = ['key' => 'now_playing_artwork', 'value' => $artworkUrl];
                $targetArtId ? $settingsDb->update($targetArtId, $artData) : $settingsDb->insert($artData);
            }
            
            // Promazání historie songů starší než 1 měsíc
            $oneMonthAgo = date('Y-m-d H:i:s', strtotime('-1 month'));
            foreach ($songsDb->getAll() as $id => $record) {
                if (is_array($record) && isset($record['played_at']) && $record['played_at'] < $oneMonthAgo) { $songsDb->delete($id); }
            }
        }
        
        $response = ['status' => 'success', 'listeners' => $listeners];
    }
    
    } catch (\Throwable $e) {
        $response = ['status' => 'error', 'message' => 'Kritická chyba API: ' . $e->getMessage() . ' na řádku ' . $e->getLine()];
    }
    
    echo json_encode($response);
    exit;
}

$settingsDb = new JsonDB('settings');
$tpl = ['color_bg1' => '#1e3c72', 'color_bg2' => '#2a5298', 'color_accent' => '#00d2ff', 'font_family' => "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif", 'bg_image' => '', 'bg_repeat' => 'cover', 'color_btn' => '#00d2ff', 'color_btn_text' => '#000000', 'color_text_muted' => '#cccccc', 'color_panel_bg' => 'rgba(255, 255, 255, 0.15)'];
$tinymceKey = '';
foreach ($settingsDb->getAll() as $row) {
    if (is_array($row) && isset($row['key']) && $row['key'] === 'template' && is_array($row['value'])) { $tpl = array_merge($tpl, $row['value']); }
    if (is_array($row) && isset($row['key']) && $row['key'] === 'tinymce_api_key') { $tinymceKey = $row['value']; }
}
$tinymceSrc = !empty($tinymceKey) ? "https://cdn.tiny.cloud/1/{$tinymceKey}/tinymce/6/tinymce.min.js" : "https://cdnjs.cloudflare.com/ajax/libs/tinymce/6.8.2/tinymce.min.js";
?>
<?php if (!$currentUser): ?>
<!DOCTYPE html>
<html lang="cs">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Přihlášení | Radio Web System</title>
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap" rel="stylesheet">
    <style>
        body { margin: 0; padding: 0; font-family: 'Montserrat', sans-serif; background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%); color: #fff; height: 100vh; display: flex; align-items: center; justify-content: center; }
        .glass { background: rgba(255,255,255,0.1); backdrop-filter: blur(20px); border: 1px solid rgba(255,255,255,0.2); box-shadow: 0 8px 32px 0 rgba(0,0,0,0.5); border-radius: 15px; }
        input, button { width: 100%; box-sizing: border-box; margin-bottom: 15px; padding: 12px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.2); background: rgba(0,0,0,0.2); color: white; outline: none; }
        button { background: linear-gradient(135deg, #00d2ff 0%, #3a7bd5 100%); font-weight: bold; cursor: pointer; border: none; transition: transform 0.2s ease; }
        button:hover { transform: scale(1.02); }
        .pwd-wrapper { position: relative; display: flex; align-items: center; width: 100%; }
        .pwd-wrapper input { padding-right: 40px !important; margin-bottom: 0 !important; width: 100%; }
        .pwd-toggle { position: absolute; right: 8px; background: none; border: none; color: inherit; cursor: pointer; font-size: 1.2rem; margin: 0; padding: 0; width: auto; }
        .pwd-toggle:hover { transform: scale(1.1); }
    </style>
</head>
<body>
    <div class="glass" style="padding: 40px; width: 100%; max-width: 350px; text-align: center;">
        <h2 style="margin-top:0;">📻<br>Radio Web System</h2>
        <form id="loginForm">
            <input type="text" id="logUser" placeholder="Uživatelské jméno" required style="width: 100%; margin-bottom: 15px;">
            <div class="pwd-wrapper" style="margin-bottom: 15px;">
                <input type="password" id="logPass" placeholder="Heslo" required style="margin-bottom: 0;">
                <button type="button" class="pwd-toggle" onclick="togglePwd('logPass', this)">👁️</button>
            </div>
            <button type="submit">Přihlásit se</button>
            <div id="logErr" style="color:#ff4b2b; display:none; margin-top:10px; font-weight:bold;"></div>
        </form>
    </div>
    <script>
        function togglePwd(id, btn) {
            const input = document.getElementById(id);
            if (input.type === 'password') { input.type = 'text'; btn.innerText = '🙈'; }
            else { input.type = 'password'; btn.innerText = '👁️'; }
        }
        document.getElementById('loginForm').addEventListener('submit', async e => {
            e.preventDefault();
            const res = await fetch('/admin/api/login', { method: 'POST', body: JSON.stringify({username: document.getElementById('logUser').value, password: document.getElementById('logPass').value}) });
            const json = await res.json();
            if(json.status === 'success') location.reload();
            else { document.getElementById('logErr').innerText = json.message; document.getElementById('logErr').style.display = 'block'; }
        });
    </script>
</body>
</html>
<?php exit; endif; ?>
<!DOCTYPE html>
<html lang="cs">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Radio Web System | Administrace</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="<?php echo htmlspecialchars($tinymceSrc); ?>" referrerpolicy="origin"></script>
    <link href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,700;1,400&family=Montserrat:wght@400;700&family=Open+Sans:wght@400;700&family=Oswald:wght@400;700&family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Roboto:wght@400;700&display=swap" rel="stylesheet">
    <style>
        :root {
            --glass-bg: <?php echo htmlspecialchars($tpl['color_panel_bg']); ?>;
            --glass-border: rgba(255, 255, 255, 0.25);
            --glass-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.5);
            --text-color: #fff;
            --accent: <?php echo htmlspecialchars($tpl['color_accent']); ?>;
            --btn-bg: <?php echo htmlspecialchars($tpl['color_btn']); ?>;
            --btn-text: <?php echo htmlspecialchars($tpl['color_btn_text']); ?>;
            --text-muted: <?php echo htmlspecialchars($tpl['color_text_muted']); ?>;
        }
        
        body {
            margin: 0; padding: 0; font-family: <?php echo $tpl['font_family']; ?>;
            <?php if (!empty($tpl['bg_image'])): ?>
                background: url('/<?php echo htmlspecialchars($tpl['bg_image']); ?>') <?php echo $tpl['bg_repeat'] === 'cover' ? 'center center / cover no-repeat' : 'repeat'; ?> fixed;
            <?php else: ?>
                background: linear-gradient(135deg, <?php echo htmlspecialchars($tpl['color_bg1']); ?> 0%, <?php echo htmlspecialchars($tpl['color_bg2']); ?> 100%) fixed;
            <?php endif; ?>
            color: var(--text-color); height: 100vh; display: flex; overflow: hidden;
        }
        .glass { background: var(--glass-bg); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid var(--glass-border); box-shadow: var(--glass-shadow); border-radius: 15px; }
        .sidebar { width: 250px; margin: 20px; padding: 20px; display: flex; flex-direction: column; gap: 15px; overflow-y: auto; }
        .content-area { flex: 1; margin: 20px 20px 20px 0; padding: 30px; overflow-y: auto; }
        .sidebar h2 { margin-top: 0; font-size: 1.2rem; text-align: center; border-bottom: 1px solid var(--glass-border); padding-bottom: 15px; }
        .nav-link { color: var(--text-color); text-decoration: none; padding: 10px 15px; border-radius: 8px; transition: all 0.3s ease; background: rgba(255,255,255, 0.05); }
        .nav-link:hover, .nav-link.active { background: rgba(255,255,255, 0.2); box-shadow: 0 4px 15px rgba(0,0,0,0.2); }
        input, select, button { background: rgba(0,0,0, 0.2); border: 1px solid var(--glass-border); color: white; padding: 10px; border-radius: 8px; outline: none; }
        button { cursor: pointer; background: var(--btn-bg); color: var(--btn-text); border: none; font-weight: bold; transition: transform 0.2s ease; }
        button:hover { transform: scale(1.05); }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { padding: 8px 12px; text-align: left; border-bottom: 1px solid var(--glass-border); } /* Optimalizace zobrazeni tabulek v Kalendari */
        th { background: rgba(255,255,255, 0.1); }
        .action-btn { padding: 5px 10px; font-size: 0.85rem; margin-right: 5px; }
        .btn-delete { background: #ff4b2b; color: #fff; }
        .btn-info { background: #11998e; color: #fff; text-decoration: none; display: inline-block; }
        .form-group { display: flex; gap: 15px; margin-bottom: 20px; align-items: center; }
        .modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(25px); -webkit-backdrop-filter: blur(25px); z-index: 1000; align-items: center; justify-content: center; }
        .modal-content { background: rgba(255, 255, 255, 0.15); backdrop-filter: blur(20px); padding: 30px; border-radius: 15px; border: 1px solid var(--glass-border); width: 400px; max-width: 90%; color: white; box-shadow: var(--glass-shadow); }
        .modal-content h3 { margin-top: 0; }
        .checkbox-group { display: flex; flex-direction: column; gap: 10px; margin: 15px 0; max-height: 200px; overflow-y: auto; padding: 10px; background: rgba(0,0,0,0.2); border-radius: 8px; }
        .checkbox-group label { display: flex; align-items: center; gap: 10px; cursor: pointer; }
        
        .pwd-wrapper { position: relative; display: flex; align-items: center; width: 100%; }
        .pwd-wrapper input { padding-right: 40px !important; margin-bottom: 0 !important; width: 100%; }
        .pwd-toggle { position: absolute; right: 8px; background: none; border: none; color: inherit; cursor: pointer; font-size: 1.2rem; margin: 0; padding: 0; width: auto; }
        .pwd-toggle:hover { transform: scale(1.1); }
        .api-link { font-size: 0.85rem; color: var(--accent); text-decoration: none; margin-left: 10px; font-weight: normal; }
        .api-link:hover { text-decoration: underline; }
    </style>
</head>
<body>
    <?php
    $settingsDbGlob = new JsonDB('settings');
    $licenseInfo = null;
    foreach ($settingsDbGlob->getAll() as $row) {
        if (is_array($row) && isset($row['key']) && $row['key'] === 'license_info') { $licenseInfo = $row['value']; break; }
    }
    $licenseBlocked = false;
    if ($licenseInfo) {
        if (($licenseInfo['license'] ?? '') !== 'OK') {
            $licenseBlocked = true;
        } elseif (!empty($licenseInfo['valid_until']) && $licenseInfo['valid_until'] !== '-') {
            $parts = explode('.', $licenseInfo['valid_until']);
            if (count($parts) === 3) {
                $expTs = strtotime(trim($parts[2]).'-'.trim($parts[1]).'-'.trim($parts[0]).' 23:59:59');
                if ($expTs && (time() - $expTs) > 30 * 86400) { $licenseBlocked = true; }
            }
        }
    }
    ?>
    <div class="sidebar glass">
        <h2>📻 Radio Web System</h2>
            <?php if (hasAccess('dashboard')): ?><a href="/admin/dashboard" class="nav-link <?php echo $mainSection === 'dashboard' ? 'active' : ''; ?>">📊 Dashboard</a><?php endif; ?>
            <?php if (!$licenseBlocked): ?>
            <?php if (hasAccess('pages')): ?><a href="/admin/pages" class="nav-link <?php echo $mainSection === 'pages' ? 'active' : ''; ?>">📄 Stránky a Články</a><?php endif; ?>
            <?php if (hasAccess('podcasts')): ?><a href="/admin/podcasts" class="nav-link <?php echo $mainSection === 'podcasts' ? 'active' : ''; ?>">🎙️ Podcasty a Záznamy</a><?php endif; ?>
            <?php if (hasAccess('requests')): ?><a href="/admin/requests" class="nav-link <?php echo $mainSection === 'requests' ? 'active' : ''; ?>">🎵 Písničky na přání</a><?php endif; ?>
            <?php if (hasAccess('moderators')): ?><a href="/admin/moderators" class="nav-link <?php echo $mainSection === 'moderators' ? 'active' : ''; ?>">🎧 Správa moderátorů</a><?php endif; ?>
            <?php if (hasAccess('calendar')): ?><a href="/admin/calendar" class="nav-link <?php echo $mainSection === 'calendar' ? 'active' : ''; ?>">📅 Kalendář směn</a><?php endif; ?>
            <?php if (hasAccess('ads')): ?><a href="/admin/ads" class="nav-link <?php echo $mainSection === 'ads' ? 'active' : ''; ?>">💰 Reklama a Obchod</a><?php endif; ?>
            <?php if (hasAccess('songs')): ?><a href="/admin/songs" class="nav-link <?php echo $mainSection === 'songs' ? 'active' : ''; ?>">📜 Historie songů</a><?php endif; ?>
            <?php if (hasAccess('stats')): ?><a href="/admin/stats" class="nav-link <?php echo $mainSection === 'stats' ? 'active' : ''; ?>">📈 Statistiky (Stream a Web)</a><?php endif; ?>
            <?php if (hasAccess('template')): ?><a href="/admin/template" class="nav-link <?php echo $mainSection === 'template' ? 'active' : ''; ?>">🎨 Vzhled a Menu webu</a><?php endif; ?>
            <?php endif; ?>
            <?php if (hasAccess('settings')): ?><a href="/admin/settings" class="nav-link <?php echo $mainSection === 'settings' ? 'active' : ''; ?>">⚙️ Nastavení systému</a><?php endif; ?>
            <?php if (($currentUser['role'] ?? '') === 'admin'): ?><a href="/admin/users" class="nav-link <?php echo $mainSection === 'users' ? 'active' : ''; ?>">👥 Správa uživatelů</a><?php endif; ?>
            <?php if (($currentUser['role'] ?? '') === 'admin'): ?><a href="/admin/activity" class="nav-link <?php echo $mainSection === 'activity' ? 'active' : ''; ?>">📋 Log aktivit</a><?php endif; ?>
        <a href="/" class="nav-link" target="_blank" style="margin-top: 20px; background: rgba(0, 210, 255, 0.2); text-align: center;">🌍 Otevřít web</a>
            <a href="/admin/logout" class="nav-link" style="margin-top: 10px; background: rgba(255, 75, 43, 0.2); text-align: center;">🚪 Odhlásit se</a>
    </div>

    <script>
        function togglePwd(id, btn) {
            const input = document.getElementById(id);
            if (input.type === 'password') { input.type = 'text'; btn.innerText = '🙈'; }
            else { input.type = 'password'; btn.innerText = '👁️'; }
        }
        function setTinyContent(id, content) { if(tinymce.get(id)) tinymce.get(id).setContent(content || ''); else document.getElementById(id).value = content || ''; }
        function getTinyContent(id) { if(tinymce.get(id)) return tinymce.get(id).getContent(); return document.getElementById(id).value; }
        tinymce.init({ selector: '.tinymce', plugins: 'advlist autolink lists link image charmap preview anchor pagebreak searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking table emoticons template help', toolbar: 'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | code', toolbar_mode: 'floating', skin: 'oxide-dark', content_css: 'dark', setup: function (editor) { editor.on('change', function () { editor.save(); }); } });
    </script>
    <div class="modal-overlay" id="customAlertModal" style="z-index:9999;">
        <div class="modal-content" style="width:600px; max-width:95%; text-align:center; display:flex; flex-direction:column; max-height:90vh;">
            <h3 id="customAlertTitle" style="color:var(--accent); flex-shrink:0; margin-top:0;">Upozornění</h3>
            <div id="customAlertText" style="margin: 20px 0; overflow-y: auto; text-align: left; word-break: break-word; white-space: pre-wrap; font-size: 0.9rem; flex:1;"></div>
            <button onclick="document.getElementById('customAlertModal').style.display='none'; if(window.customAlertCallback) window.customAlertCallback();" style="flex-shrink:0;">OK</button>
        </div>
    </div>
    
    <div class="modal-overlay" id="customConfirmModal" style="z-index:9999;">
        <div class="modal-content" style="width:400px; text-align:center;">
            <h3 id="customConfirmTitle" style="color:#ff4b2b;">Potvrzení akce</h3>
            <p id="customConfirmText" style="margin: 20px 0;"></p>
            <div style="display:flex; gap:10px; justify-content:center;">
                <button onclick="document.getElementById('customConfirmModal').style.display='none'; if(window.customConfirmOk) window.customConfirmOk();" style="background:#ff4b2b; color:#fff;">Ano, provést</button>
                <button onclick="document.getElementById('customConfirmModal').style.display='none';" style="background:rgba(255,255,255,0.2);">Zrušit</button>
            </div>
        </div>
    </div>
    <script>
        window.customAlert = function(text, title='Upozornění', callback=null) {
            document.getElementById('customAlertTitle').innerText = title;
            document.getElementById('customAlertText').innerText = text;
            window.customAlertCallback = callback;
            document.getElementById('customAlertModal').style.display = 'flex';
        };
        window.customConfirm = function(text, okCallback) {
            document.getElementById('customConfirmText').innerText = text;
            window.customConfirmOk = okCallback;
            document.getElementById('customConfirmModal').style.display = 'flex';
        };
        window.alert = function(text) { customAlert(text); };
        
        document.addEventListener('DOMContentLoaded', () => {
            const sidebar = document.querySelector('.sidebar');
            if (sidebar) {
                const savedScroll = localStorage.getItem('sidebarScroll');
                if (savedScroll) sidebar.scrollTop = parseInt(savedScroll);
                sidebar.addEventListener('scroll', () => { localStorage.setItem('sidebarScroll', sidebar.scrollTop); });
            }
        });
    </script>
    
    <div class="modal-overlay" id="emailComposerModal" style="z-index:9998; display:none;">
        <div class="modal-content" style="width:700px; max-width:95%;">
            <h3 id="ecTitle" style="color:var(--accent); margin-top:0;">Nová zpráva</h3>
            <form id="emailComposerForm" class="form-group" style="flex-wrap: wrap;">
                <div style="width:100%; display:flex; gap:10px;"><input type="email" id="ecTo" placeholder="Příjemce (E-mail)" required style="flex:1;"></div>
                <div style="width:100%; display:flex; gap:10px; margin-top:10px;"><input type="text" id="ecSubject" placeholder="Předmět" required style="flex:1;"></div>
                <div style="width:100%; margin-top:10px;"><textarea id="ecMessage" class="tinymce" rows="10" style="width:100%;"></textarea></div>
                <div style="width:100%; margin-top:10px; background:rgba(0,0,0,0.2); padding:10px; border-radius:8px; border:1px solid var(--glass-border);">
                    <div style="margin-bottom:5px; font-weight:bold; font-size:0.9rem;">Přílohy:</div>
                    <div id="ecSystemAttachments" style="font-size:0.85rem; color:var(--accent); margin-bottom:5px;"></div>
                    <input type="file" id="ecAttachments" multiple style="width:100%; font-size:0.85rem;">
                </div>
                <div style="width:100%; margin-top:15px; display:flex; justify-content:flex-end; gap:10px;">
                    <button type="button" onclick="closeEmailComposer()" style="background:rgba(255,255,255,0.2);">Zrušit</button>
                    <button type="submit" id="ecSubmitBtn">Odeslat e-mail</button>
                </div>
            </form>
        </div>
    </div>
    <script>
        window.openEmailComposer = async function(toEmail = '', subject = '', message = '', systemAttachmentDesc = '', apiEndpoint = '/admin/api/send-email', extraData = {}) {
            document.getElementById('ecTo').value = toEmail; document.getElementById('ecSubject').value = subject;
            let signature = ''; try { const res = await fetch('/admin/api/settings-config'); const json = await res.json(); if (json.data && json.data.email_signature) signature = '<br><br>' + json.data.email_signature; } catch(e){}
            setTinyContent('ecMessage', message + signature);
            document.getElementById('ecSystemAttachments').innerHTML = systemAttachmentDesc ? '📎 ' + systemAttachmentDesc : '';
            document.getElementById('ecAttachments').value = '';
            window.ecCurrentApiEndpoint = apiEndpoint; window.ecExtraData = extraData;
            document.getElementById('emailComposerModal').style.display = 'flex';
        };
        window.closeEmailComposer = function() { document.getElementById('emailComposerModal').style.display = 'none'; };
        document.getElementById('emailComposerForm').addEventListener('submit', async function(e) {
            e.preventDefault(); const btn = document.getElementById('ecSubmitBtn'); const origText = btn.innerText; btn.innerText = 'Odesílám...'; btn.disabled = true;
            const formData = new FormData(); formData.append('to', document.getElementById('ecTo').value); formData.append('subject', document.getElementById('ecSubject').value); formData.append('message', getTinyContent('ecMessage'));
            if (window.ecExtraData) { for (const key in window.ecExtraData) { formData.append(key, window.ecExtraData[key]); } }
            const files = document.getElementById('ecAttachments').files; for (let i = 0; i < files.length; i++) { formData.append('attachments[]', files[i]); }
            try { const res = await fetch(window.ecCurrentApiEndpoint, { method: 'POST', body: formData }); const text = await res.text(); let json; try { json = JSON.parse(text); } catch(e) { json = {status:'error', message: text}; }
                if (json.status === 'success') { customAlert(json.message || 'E-mail byl úspěšně odeslán.', 'Hotovo'); closeEmailComposer(); } else { customAlert('Chyba: ' + json.message, 'Chyba odesílání'); }
            } catch (err) { customAlert('Nastala síťová chyba při odesílání.', 'Chyba sítě'); }
            btn.innerText = origText; btn.disabled = false;
        });
    </script>

    <div class="content-area <?php echo $mainSection !== 'requests-studio' ? 'glass' : ''; ?>" <?php if ($mainSection === 'requests-studio') echo 'style="margin: 10px; padding: 15px; display: flex; flex-direction: column;"'; ?>>
        <?php if ($mainSection !== 'dashboard' && $mainSection !== 'requests-studio' && $mainSection !== 'users' && !hasAccess($mainSection)): ?>
            <h1>Přístup odepřen</h1>
            <p>Nemáte oprávnění k zobrazení tohoto modulu administrace.</p>
            <a href="/admin/logout" style="display:inline-block; margin-top:20px; padding:10px 20px; background:var(--glass-border); color:#fff; text-decoration:none; border-radius:8px;">Odhlásit se a přihlásit znovu</a>
        <?php else: ?>
            <?php 
                if ($licenseBlocked && !in_array($mainSection, ['dashboard', 'settings', 'logout', 'api'])) {
                    echo "<h1 style='color:#ff4b2b;'>Licence uzamčena</h1><p style='font-size:1.2rem;'>Platnost vaší licence systému vypršela o více než 30 dní, nebo byla označena jako neplatná. Přístup k produkčním funkcím byl omezen.</p><p>Prohlédněte si aktuální stav na nástěnce (Dashboard), kde si můžete licenci jediným kliknutím prodloužit.</p>";
                } else {
                $viewFile = __DIR__ . '/admin_' . str_replace('-', '_', $mainSection) . '.php';
                if (file_exists($viewFile)) {
                    include $viewFile;
                } else {
                    echo "<h1>404 - Modul nenalezen</h1><p>Požadovaná sekce administrace (" . htmlspecialchars($mainSection) . ") neexistuje.</p>";
                }
                }
            ?>
        <?php endif; ?>
    </div>
</body>
</html>
