<?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 {
    $result = [
        'listener_connections' => 0,
        'listeners' => 0,
        'mount' => '/autodj',
        'mount_listeners' => 0,
        'server_name' => 'Underground FX AutoDJ',
        '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('/\blisteners\s+([0-9,]+)/i', $plain, $m)) {
        $result['listeners'] = (int) str_replace(',', '', $m[1]);
    }

    $section = $plain;
    if (preg_match('/Mountpoint\s+(\/autodj)([\s\S]*?)(?:Mountpoint\s+\/stream|Mount Authentication|$)/i', $plain, $sec)) {
        $section = $sec[0];
        $result['mount'] = '/autodj';
    }

    if (preg_match('/x_icy_title\s+([^\r\n]+?)(?:\s+(?:x_icy_url|Playlist|Mount Authentication|content-type)\b|$)/i', $section, $m)) {
        $result['title'] = trim($m[1]);
    }
    if (preg_match('/server_name\s+([^\r\n]+?)(?:\s+(?:server_type|server_url|slow_listeners|source_ip)\b|$)/i', $section, $m)) {
        $result['server_name'] = trim($m[1]);
    }
    if (preg_match('/Mountpoint\s+\/autodj[\s\S]*?\blisteners\s+([0-9,]+)/i', $section, $m)) {
        $result['mount_listeners'] = (int) str_replace(',', '', $m[1]);
    } elseif (preg_match('/\blisteners\s+([0-9,]+)/i', $section, $m)) {
        $result['mount_listeners'] = (int) str_replace(',', '', $m[1]);
    }

    return $result;
}

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

    $cfg = ugfx_get_stream_config();
    $publicStream = trim((string)($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' => trim((string)($cfg['mount_main'] ?? '/autodj')),
        'stream_url' => '/stream-proxy.php',
        'public_stream_url' => $publicStream,
        'direct_stream_url' => $publicStream,
        'status' => 'LIVE'
    ];

    $xml = ugfx_fetch_icecast_xml();
    if ($xml !== '') {
        $parsed = ugfx_parse_icecast_data($xml);
        $source = ugfx_pick_preferred_source($parsed['sources'] ?? []);
        $rawTitle = trim((string)($source['title'] ?? ''));
        $artist = trim((string)($source['server_name'] ?? 'Underground FX AutoDJ'));
        $title = $rawTitle !== '' ? $rawTitle : 'Underground FX Live';

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

        $data = [
            'server_listeners' => (int)($parsed['global']['listener_connections'] ?? ($parsed['global']['listeners'] ?? 0)),
            'current_listeners' => (int)($source['listeners'] ?? 0),
            'title' => $title,
            'artist' => $artist,
            'mount' => (string)($source['mount'] ?? ($cfg['mount_main'] ?? '/stream')),
            '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;
    }

    $statsXslUrl = trim((string)($cfg['stats_xsl_url'] ?? ''));
    $statsHtml = '';
    if ($statsXslUrl !== '' && function_exists('ugfx_fetch_with_basic_auth')) {
        $statsHtml = ugfx_fetch_with_basic_auth([$statsXslUrl], (string)($cfg['admin_user'] ?? ''), (string)($cfg['admin_password'] ?? ''));
    }
    if ($statsHtml !== '') {
        $parsedXsl = ugfx_parse_stats_xsl($statsHtml);
        $title = trim((string)($parsedXsl['title'] ?? ''));
        $artist = trim((string)($parsedXsl['server_name'] ?? 'Underground FX AutoDJ'));
        if ($title === '') $title = 'Underground FX Live';
        if (strpos($title, ' - ') !== false) {
            list($artistPart, $titlePart) = array_map('trim', explode(' - ', $title, 2));
            if ($artistPart !== '') $artist = $artistPart;
            if ($titlePart !== '') $title = $titlePart;
        }
        $data = [
            'server_listeners' => (int)($parsedXsl['listener_connections'] ?? ($parsedXsl['listeners'] ?? 0)),
            'current_listeners' => (int)($parsedXsl['mount_listeners'] ?? 0),
            'title' => $title,
            'artist' => $artist,
            'mount' => (string)($parsedXsl['mount'] ?? ($cfg['mount_main'] ?? '/stream')),
            '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;
    }

    if (is_file($cacheFile)) {
        $stale = json_decode((string)@file_get_contents($cacheFile), true);
        if (is_array($stale)) {
            return $cached = $stale;
        }
    }
    return $cached = $fallback;}

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;
}
?>
