<?php
function ugfx_read_json(string $path, $default = []) {
    if (!file_exists($path)) return $default;
    $data = json_decode(file_get_contents($path), true);
    return is_array($data) ? $data : $default;
}

function ugfx_write_json(string $path, $data): bool {
    $dir = dirname($path);
    if (!is_dir($dir)) mkdir($dir, 0775, true);
    return (bool) file_put_contents($path, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}

function ugfx_asset(string $path): string {
    return 'assets/' . ltrim($path, '/');
}

function ugfx_vendor_asset(string $localPath, string $cdnUrl, string $prefix = ''): string {
    $normalized = ltrim($localPath, '/');
    $absolute = dirname(__DIR__) . '/' . $normalized;
    if (file_exists($absolute)) {
        return $prefix . $normalized;
    }
    return $cdnUrl;
}

function ugfx_is_active(string $page, string $current): string {
    return $page === $current ? 'active' : '';
}

function ugfx_slugify(string $text): string {
    $text = strtolower(trim($text));
    $text = preg_replace('/[^a-z0-9]+/', '-', $text);
    return trim($text ?? '', '-') ?: 'page';
}

function ugfx_strlen(string $text): int {
    return function_exists('mb_strlen') ? mb_strlen($text) : strlen($text);
}

function ugfx_substr(string $text, int $start, ?int $length = null): string {
    if (function_exists('mb_substr')) {
        return $length === null ? mb_substr($text, $start) : mb_substr($text, $start, $length);
    }
    return $length === null ? substr($text, $start) : substr($text, $start, $length);
}

function ugfx_excerpt(string $text, int $length = 180): string {
    $text = trim(strip_tags($text));
    return ugfx_strlen($text) > $length ? ugfx_substr($text, 0, $length - 1) . '…' : $text;
}

function ugfx_sort_items_by_date_desc(array $items): array {
    usort($items, function ($a, $b) {
        return strtotime((string)($b['start'] ?? $b['date'] ?? '')) <=> strtotime((string)($a['start'] ?? $a['date'] ?? ''));
    });
    return $items;
}

function ugfx_get_news(int $limit = 6): array {
    global $ugfx;
    $items = ugfx_read_json($ugfx['storage']['news'], []);
    $items = array_values(array_filter($items, function ($item) { return ($item['published'] ?? 0) == 1; }));
    return array_slice($items, 0, $limit);
}

function ugfx_get_events(int $limit = 4): array {
    global $ugfx;
    $items = ugfx_read_json($ugfx['storage']['events'], []);
    $items = array_values(array_filter($items, function ($item) { return ($item['published'] ?? 0) == 1; }));
    $items = ugfx_sort_items_by_date_desc($items);
    return array_slice($items, 0, $limit);
}

function ugfx_get_djs(int $limit = 8): array {
    global $ugfx;
    return array_slice(ugfx_read_json($ugfx['storage']['djs'], []), 0, $limit);
}

function ugfx_get_top50(int $limit = 10): array {
    global $ugfx;
    $items = ugfx_read_json($ugfx['storage']['top50'], []);
    uasort($items, function ($a, $b) { return ($b['count'] ?? 0) <=> ($a['count'] ?? 0); });
    return array_slice($items, 0, $limit, true);
}

function ugfx_get_schedule(): array {
    global $ugfx;
    return ugfx_read_json($ugfx['storage']['schedule'], []);
}

function ugfx_get_friends(int $limit = 12): array {
    global $ugfx;
    return array_slice(ugfx_read_json($ugfx['storage']['friends'], []), 0, $limit);
}

function ugfx_get_pages(bool $publishedOnly = true): array {
    global $ugfx;
    $items = ugfx_read_json($ugfx['storage']['pages'], []);
    if ($publishedOnly) {
        $items = array_values(array_filter($items, function ($item) { return ($item['published'] ?? 0) == 1; }));
    }
    return $items;
}

function ugfx_get_page_by_slug(string $slug): ?array {
    foreach (ugfx_get_pages(false) as $page) {
        if (($page['slug'] ?? '') === $slug) {
            return $page;
        }
    }
    return null;
}

function ugfx_day_name(?int $timestamp = null): string {
    return date('l', $timestamp ?? time());
}

function ugfx_current_show(): array {
    $schedule = ugfx_get_schedule();
    $day = ugfx_day_name();
    $hour = (int) date('G');
    $current = $schedule[$day][$hour] ?? 'Underground FX Live';
    $next = $schedule[$day][($hour + 1) % 24] ?? 'Underground FX Live';
    return ['day' => $day, 'hour' => $hour, 'current' => $current, 'next' => $next];
}


function ugfx_fetch_with_basic_auth(array $urls, string $user, string $pass): string {
    foreach ($urls as $url) {
        $url = trim((string)$url);
        if ($url === '') continue;

        if (function_exists('curl_init')) {
            $ch = curl_init($url);
            curl_setopt_array($ch, [
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
                CURLOPT_USERPWD => $user . ':' . $pass,
                CURLOPT_TIMEOUT => 6,
                CURLOPT_CONNECTTIMEOUT => 4,
                CURLOPT_FAILONERROR => false,
                CURLOPT_HTTPHEADER => ['Accept: application/xml, text/xml, text/html, */*'],
            ]);
            $raw = curl_exec($ch);
            $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            if (is_string($raw) && trim($raw) !== '' && $code < 400) {
                return $raw;
            }
        }

        $context = stream_context_create([
            'http' => [
                'timeout' => 6,
                'ignore_errors' => true,
                'header' => "Authorization: Basic " . base64_encode($user . ':' . $pass) . "\r\n" .
                            "Accept: application/xml, text/xml, text/html, */*\r\n"
            ]
        ]);
        $raw = @file_get_contents($url, false, $context);
        if (is_string($raw) && trim($raw) !== '') {
            return $raw;
        }
    }
    return '';
}

function ugfx_parse_stats_xsl(string $html): array {
    $cfg = ugfx_get_stream_config();
    $preferredMount = ugfx_normalize_mount((string)($cfg['mount_main'] ?? '/stream'));
    $autoMount = ugfx_normalize_mount((string)($cfg['mount_auto'] ?? '/autodj'));

    $result = [
        'listener_connections' => 0,
        'listeners' => 0,
        'mount' => $preferredMount,
        'mount_listeners' => 0,
        'server_name' => 'Underground FX Radio',
        'title' => '',
    ];

    $plain = html_entity_decode(strip_tags($html), ENT_QUOTES, 'UTF-8');
    $plain = preg_replace('/\s+/', ' ', $plain);

    if (preg_match('/listener_connections\s+([0-9,]+)/i', $plain, $m)) {
        $result['listener_connections'] = (int) str_replace(',', '', $m[1]);
    }
    if (preg_match('/listeners\s+([0-9,]+)/i', $plain, $m)) {
        $result['listeners'] = (int) str_replace(',', '', $m[1]);
    }

    foreach ([$preferredMount, $autoMount] as $candidateMount) {
        $pattern = '/Mountpoint\s+' . preg_quote($candidateMount, '/') . '([\s\S]*?)(?:Mountpoint\s+\/[^\s]+|Mount Authentication|$)/i';
        if (!preg_match($pattern, $plain, $sec)) {
            continue;
        }
        $section = $sec[0];
        $result['mount'] = $candidateMount;
        if (preg_match('/x_icy_title\s+([^
]+?)(?:\s+(?:x_icy_url|Playlist|Mount Authentication|content-type|audio_info)|$)/i', $section, $m)) {
            $result['title'] = trim($m[1]);
        }
        if (preg_match('/server_name\s+([^
]+?)(?:\s+(?:server_type|server_url|slow_listeners|source_ip|public|genre)|$)/i', $section, $m)) {
            $result['server_name'] = trim($m[1]);
        }
        if (preg_match('/listeners\s+([0-9,]+)/i', $section, $m)) {
            $result['mount_listeners'] = (int) str_replace(',', '', $m[1]);
        }
        if ($result['title'] !== '' || $result['mount_listeners'] > 0) {
            break;
        }
    }

    return $result;
}

function ugfx_icecast_status(): array {
    static $cached = null;
    if ($cached !== null) {
        return $cached;
    }

    $cfg = ugfx_get_stream_config();
    $playerUrls = ugfx_get_player_urls();
    $publicStream = trim((string)($playerUrls['raw'] ?? ($cfg['listen_url'] ?? 'http://radio.undergroundfxradio.com:9000/stream')));
    $cacheFile = __DIR__ . '/../data/icecast_stats_cache.json';
    $cacheTtl = 15;

    if (is_file($cacheFile) && (time() - (int)filemtime($cacheFile) <= $cacheTtl)) {
        $cachedData = json_decode((string)@file_get_contents($cacheFile), true);
        if (is_array($cachedData) && isset($cachedData['server_listeners'])) {
            return $cached = $cachedData;
        }
    }

    $fallback = [
        'server_listeners' => 0,
        'current_listeners' => 0,
        'title' => 'Underground FX Live',
        'artist' => 'Underground FX AutoDJ',
        'mount' => ugfx_normalize_mount((string)($cfg['mount_main'] ?? '/stream')),
        'stream_url' => $publicStream !== '' ? $publicStream : '/stream-proxy.php',
        'proxy_stream_url' => '/stream-proxy.php',
        'public_stream_url' => $publicStream,
        'direct_stream_url' => $publicStream,
        'status' => 'LIVE'
    ];

    $xml = ugfx_fetch_icecast_xml();
    $parsed = ugfx_parse_icecast_data($xml);
    $source = ugfx_pick_preferred_source($parsed['sources'] ?? []);
    $serverListeners = (int)($parsed['global']['listener_connections'] ?? ($parsed['global']['listeners'] ?? 0));
    $sourceSum = 0;
    foreach (($parsed['sources'] ?? []) as $src) {
        $sourceSum += (int)($src['listeners'] ?? 0);
    }
    if ($sourceSum > $serverListeners) {
        $serverListeners = $sourceSum;
    }

    $rawTitle = trim((string)($source['title'] ?? ''));
    $artist = trim((string)($source['server_name'] ?? 'Underground FX AutoDJ'));
    $title = $rawTitle !== '' ? $rawTitle : 'Underground FX Live';
    $currentListeners = (int)($source['listeners'] ?? 0);
    $mount = (string)($source['mount'] ?? ($cfg['mount_main'] ?? '/stream'));

    if ($xml === '' || ($serverListeners <= 0 && $currentListeners <= 0 && $rawTitle === '')) {
        $xsl = ugfx_fetch_icecast_xsl();
        if ($xsl !== '') {
            $xslData = ugfx_parse_stats_xsl($xsl);
            if ($serverListeners <= 0) {
                $serverListeners = max((int)($xslData['listener_connections'] ?? 0), (int)($xslData['listeners'] ?? 0), (int)($xslData['mount_listeners'] ?? 0));
            }
            if ($currentListeners <= 0) {
                $currentListeners = (int)($xslData['mount_listeners'] ?? 0);
            }
            if ($rawTitle === '') {
                $title = trim((string)($xslData['title'] ?? '')) ?: $title;
            }
            if ($artist === '' || $artist === 'Underground FX AutoDJ') {
                $artist = trim((string)($xslData['server_name'] ?? '')) ?: $artist;
            }
            if ($mount === '' || $mount === '/') {
                $mount = (string)($xslData['mount'] ?? $mount);
            }
        }
    }

    if (strpos($title, ' - ') !== false) {
        list($artistPart, $titlePart) = array_map('trim', explode(' - ', $title, 2));
        if ($artistPart !== '') $artist = $artistPart;
        if ($titlePart !== '') $title = $titlePart;
    }

    $data = [
        'server_listeners' => max(0, (int)$serverListeners),
        'current_listeners' => max(0, (int)$currentListeners),
        'title' => $title ?: 'Underground FX Live',
        'artist' => $artist ?: 'Underground FX AutoDJ',
        'mount' => ugfx_normalize_mount((string)$mount),
        'stream_url' => $publicStream !== '' ? $publicStream : '/stream-proxy.php',
        'proxy_stream_url' => '/stream-proxy.php',
        'public_stream_url' => $publicStream,
        'direct_stream_url' => $publicStream,
        'status' => 'LIVE'
    ];

    @file_put_contents($cacheFile, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), LOCK_EX);
    return $cached = $data;
}

function ugfx_now_playing(): array {
    $show = ugfx_current_show();
    $icecast = ugfx_icecast_status();
    return [
        'title' => $icecast['title'] ?: 'Underground FX Live',
        'artist' => $icecast['artist'] ?: $show['current'],
        'album' => 'Underground FX Radio',
        'art' => ugfx_asset('img/brand/ugfx-hero.png'),
        'listeners' => $icecast['server_listeners'],
        'current_listeners' => $icecast['current_listeners'],
        'status' => $icecast['status'],
        'mount' => $icecast['mount'],
        'stream_url' => $icecast['stream_url'],
        'public_stream_url' => $icecast['public_stream_url'] ?? '',
        'direct_stream_url' => $icecast['direct_stream_url'] ?? ''
    ];
}

function ugfx_nav_items(): array {
    return [
        ['label' => 'Home', 'href' => 'index.php'],
        ['label' => 'Listen Live', 'href' => 'listen-live.php'],
        ['label' => 'Schedule', 'href' => 'schedule.php'],
        ['label' => 'Requests', 'href' => 'requests.php'],
        ['label' => 'News', 'href' => 'news.php'],
        ['label' => 'Team', 'href' => 'team.php'],
        ['label' => 'Join', 'href' => 'join.php'],
        ['label' => 'Events', 'href' => 'events.php'],
        ['label' => 'Friends', 'href' => 'friends.php'],
        ['label' => 'Chat', 'href' => 'chat.php'],
        ['label' => 'Contact', 'href' => 'contact.php'],
    ];
}

function ugfx_safe_links(string $text): string {
    $escaped = nl2br(htmlspecialchars($text, ENT_QUOTES, 'UTF-8'));
    return preg_replace_callback('/(https?:\/\/[^\s<]+)/i', function ($matches) {
        $url = htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8');
        return '<a href="' . $url . '" target="_blank" rel="noopener noreferrer nofollow">' . $url . '</a>';
    }, $escaped);
}

function ugfx_chat_messages(): array {
    global $ugfx;
    return ugfx_read_json($ugfx['storage']['chat'], []);
}

function ugfx_chat_add(array $message): bool {
    global $ugfx;
    $messages = ugfx_chat_messages();
    $message['id'] = time() . rand(100,999);
    $messages[] = $message;
    return ugfx_write_json($ugfx['storage']['chat'], array_slice($messages, -200));
}

function ugfx_banned_words(): array {
    global $ugfx;
    return ugfx_read_json($ugfx['storage']['banned_words'], []);
}

function ugfx_contains_banned_word(string $message): bool {
    foreach (ugfx_banned_words() as $word) {
        if ($word !== '' && stripos($message, $word) !== false) return true;
    }
    return false;
}

function ugfx_require_admin(): void {
    if (empty($_SESSION['ugfx_admin'])) {
        header('Location: login.php');
        exit;
    }
}

function ugfx_admin_attempt(string $username, string $password): bool {
    global $ugfx;
    $users = ugfx_read_json($ugfx['storage']['users'], []);
    foreach ($users as $user) {
        if (($user['username'] ?? '') === $username && ($user['password'] ?? '') === $password) {
            $_SESSION['ugfx_admin'] = $user;
            return true;
        }
    }
    return false;
}
?>
