<?php
if (!function_exists('ugfx_get_stream_config')) {
function ugfx_get_stream_config(): array {
    $settingsFile = dirname(__DIR__) . '/data/settings.json';
    $settings = [];
    if (is_file($settingsFile)) {
        $decoded = json_decode((string)file_get_contents($settingsFile), true);
        if (is_array($decoded)) $settings = $decoded;
    }

    $cfg = [
        'server_ip' => trim((string)($settings['stats_host'] ?? 'cr2.broadcasturself.com')),
        'server_port' => trim((string)($settings['stats_port'] ?? '9000')),
        'admin_user' => (string)($settings['stats_user'] ?? 'UndergroundFx'),
        'admin_password' => (string)($settings['stats_password'] ?? 'TxHL7RqdSjQbSB'),
        'mount_main' => trim((string)($settings['mount_main'] ?? '/stream')),
        'mount_auto' => trim((string)($settings['stats_mount'] ?? $settings['mount_auto'] ?? '/autodj')),
        'mount_backup' => trim((string)($settings['mount_backup'] ?? '/stream2')),
        'listen_url' => trim((string)($settings['public_stream_url'] ?? $settings['stream_url'] ?? 'http://radio.undergroundfxradio.com:9000/stream')),
        'proxy_url' => '/stream-proxy.php',
        'cache_file' => dirname(__DIR__) . '/data/icecast_stats_cache.json',
        'cache_ttl' => 15,
    ];

    return $cfg;
}
}

if (!function_exists('ugfx_fetch_icecast_xml')) {
function ugfx_fetch_icecast_xml(): string {
    $cfg = ugfx_get_stream_config();
    $hostname = trim((string)($cfg['server_ip'] ?? ''));
    $port = trim((string)($cfg['server_port'] ?? ''));
    $user = (string)($cfg['admin_user'] ?? '');
    $pass = (string)($cfg['admin_password'] ?? '');

    if ($hostname === '' || $port === '' || $user === '' || $pass === '') {
        return '';
    }

    $urls = [
        "http://{$hostname}:{$port}/admin/stats",
        "http://{$hostname}:{$port}/admin/stats.xml",
    ];

    foreach ($urls as $url) {
        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, */*'],
            ]);
            $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;
            }
        }

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

    return '';
}
}

if (!function_exists('ugfx_parse_icecast_data')) {
function ugfx_parse_icecast_data(string $xml): array {
    $result = [
        'global' => [],
        'sources' => [],
    ];

    if (trim($xml) === '') return $result;

    libxml_use_internal_errors(true);
    $sx = @simplexml_load_string($xml);
    if (!$sx) {
        libxml_clear_errors();
        return $result;
    }

    $result['global'] = [
        'listeners' => isset($sx->listeners) ? (int)$sx->listeners : 0,
        'listener_connections' => isset($sx->listener_connections) ? (int)$sx->listener_connections : 0,
        'clients' => isset($sx->clients) ? (int)$sx->clients : 0,
        'sources' => isset($sx->sources) ? (int)$sx->sources : 0,
        'host' => trim((string)($sx->host ?? '')),
        'server_id' => trim((string)($sx->server_id ?? '')),
        'server_start' => trim((string)($sx->server_start_iso8601 ?? $sx->server_start ?? '')),
    ];

    if (isset($sx->source)) {
        foreach ($sx->source as $source) {
            $mount = trim((string)$source['mount']);
            $title = trim((string)$source->title);
            if ($title === '' && isset($source->x_icy_title)) {
                $title = trim((string)$source->x_icy_title);
            }
            if ($title === '' && isset($source->metadata->x_icy_title)) {
                $title = trim((string)$source->metadata->x_icy_title);
            }

            $listeners = isset($source->listeners) ? (int)$source->listeners : 0;
            $streamStart = trim((string)($source->stream_start_iso8601 ?? $source->stream_start ?? ''));
            $sourceIp = trim((string)($source->source_ip ?? ''));
            $listenUrl = trim((string)($source->listenurl ?? ''));
            $serverName = trim((string)($source->server_name ?? ''));
            $serverDescription = trim((string)($source->server_description ?? ''));

            $isActive = (
                $listeners > 0 ||
                $title !== '' ||
                $sourceIp !== '' ||
                $streamStart !== ''
            );

            $result['sources'][] = [
                'mount' => $mount,
                'title' => html_entity_decode($title, ENT_QUOTES, 'UTF-8'),
                'listeners' => $listeners,
                'stream_start' => $streamStart,
                'source_ip' => $sourceIp,
                'listenurl' => $listenUrl,
                'server_name' => $serverName,
                'server_description' => $serverDescription,
                'is_active' => $isActive,
            ];
        }
    }

    libxml_clear_errors();
    return $result;
}
}

if (!function_exists('ugfx_pick_preferred_source')) {
function ugfx_pick_preferred_source(array $sources): ?array {
    if (!$sources) return null;

    $cfg = ugfx_get_stream_config();
    $preferredMounts = [
        trim((string)($cfg['mount_main'] ?? '/stream')),
        trim((string)($cfg['mount_auto'] ?? '/autodj')),
        trim((string)($cfg['mount_backup'] ?? '/stream2')),
    ];

    foreach ($preferredMounts as $mount) {
        foreach ($sources as $source) {
            if (
                ($source['mount'] ?? '') === $mount &&
                !empty($source['is_active']) &&
                trim((string)($source['title'] ?? '')) !== '' &&
                (int)($source['listeners'] ?? 0) > 0
            ) {
                return $source;
            }
        }
    }

    foreach ($preferredMounts as $mount) {
        foreach ($sources as $source) {
            if (
                ($source['mount'] ?? '') === $mount &&
                !empty($source['is_active']) &&
                trim((string)($source['title'] ?? '')) !== ''
            ) {
                return $source;
            }
        }
    }

    foreach ($preferredMounts as $mount) {
        foreach ($sources as $source) {
            if (($source['mount'] ?? '') === $mount && !empty($source['is_active'])) {
                return $source;
            }
        }
    }

    foreach ($sources as $source) {
        if (trim((string)($source['title'] ?? '')) !== '') {
            return $source;
        }
    }

    return $sources[0] ?? null;
}
}

if (!function_exists('ugfx_fetch_stats_xsl_html')) {
function ugfx_fetch_stats_xsl_html(): string {
    $cfg = ugfx_get_stream_config();
    $host = trim((string)($cfg['server_ip'] ?? ''));
    $port = trim((string)($cfg['server_port'] ?? ''));
    $user = (string)($cfg['admin_user'] ?? '');
    $pass = (string)($cfg['admin_password'] ?? '');
    if ($host === '' || $port === '' || $user === '' || $pass === '') return '';

    $url = "http://{$host}:{$port}/admin/stats.xsl?showall=true";
    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,
        ]);
        $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;
        }
    }
    $ctx = stream_context_create([
        'http' => [
            'timeout' => 6,
            'ignore_errors' => true,
            'header' => "Authorization: Basic " . base64_encode($user . ':' . $pass) . "
"
        ]
    ]);
    $raw = @file_get_contents($url, false, $ctx);
    return is_string($raw) ? $raw : '';
}
}

if (!function_exists('ugfx_parse_stats_xsl_html')) {
function ugfx_parse_stats_xsl_html(string $html): array {
    $result = [
        'listener_connections' => 0,
        'mount' => '/autodj',
        'mount_listeners' => 0,
        'title' => '',
        'server_name' => 'Underground FX AutoDJ',
    ];
    if (trim($html) === '') return $result;

    $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('/Mountpoint\s+(\/autodj)([\s\S]*?)(?:Mountpoint\s+\/stream|Mountpoint\s+\/stream2|Mount Authentication|$)/i', $plain, $sec)) {
        $section = $sec[0];
    } else {
        $section = $plain;
    }

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

    return $result;
}
}

if (!function_exists('ugfx_fetch_icy_title')) {
function ugfx_fetch_icy_title(string $streamUrl): string {
    $parts = @parse_url($streamUrl);
    if (!$parts || empty($parts['host'])) return '';
    $scheme = strtolower((string)($parts['scheme'] ?? 'http'));
    $host = (string)$parts['host'];
    $port = (int)($parts['port'] ?? ($scheme === 'https' ? 443 : 80));
    $path = ($parts['path'] ?? '/') . (!empty($parts['query']) ? '?' . $parts['query'] : '');
    $transport = $scheme === 'https' ? 'ssl://' : '';
    $fp = @fsockopen($transport . $host, $port, $errno, $errstr, 4);
    if (!$fp) return '';
    stream_set_timeout($fp, 4);
    $out = "GET {$path} HTTP/1.0
Host: {$host}
Icy-MetaData: 1
User-Agent: UGFXNowPlaying/1.0
Connection: close

";
    fwrite($fp, $out);
    $metaInt = 0;
    while (!feof($fp)) {
        $line = fgets($fp, 512);
        if ($line === false) break;
        $trim = trim($line);
        if ($trim === '') break;
        if (stripos($trim, 'icy-metaint:') === 0) {
            $metaInt = (int)trim(substr($trim, 12));
        }
    }
    if ($metaInt <= 0) { fclose($fp); return ''; }
    $audio = '';
    while (strlen($audio) < $metaInt && !feof($fp)) {
        $audio .= fread($fp, $metaInt - strlen($audio));
    }
    $lenByte = fread($fp, 1);
    if ($lenByte === false || $lenByte === '') { fclose($fp); return ''; }
    $len = ord($lenByte) * 16;
    $metadata = $len > 0 ? fread($fp, $len) : '';
    fclose($fp);
    if (preg_match("/StreamTitle='([^']*)';/i", (string)$metadata, $mm)) {
        return html_entity_decode(trim($mm[1]), ENT_QUOTES, 'UTF-8');
    }
    return '';
}
}

if (!function_exists('ugfx_get_player_urls')) {
function ugfx_get_player_urls(): array {
    $cfg = ugfx_get_stream_config();
    return [
        'raw' => $cfg['listen_url'],
        'proxy' => $cfg['proxy_url'],
        'preferred' => $cfg['proxy_url'],
        'using_proxy' => true,
    ];
}
}

if (!function_exists('ugfx_build_status_from_streams')) {
function ugfx_build_status_from_streams(): array {
    $cfg = ugfx_get_stream_config();
    $playerUrls = ugfx_get_player_urls();
    $publicStream = trim((string)($playerUrls['raw'] ?? ''));
    $fallback = [
        'server_listeners' => 0,
        'current_listeners' => 0,
        'title' => 'Underground FX Live',
        'artist' => 'AutoDJ',
        'mount' => $cfg['mount_auto'] ?: '/autodj',
        'stream_url' => $playerUrls['preferred'],
        'public_stream_url' => $publicStream,
        'direct_stream_url' => $publicStream,
        'status' => 'LIVE'
    ];

    $xml = ugfx_fetch_icecast_xml();
    if ($xml !== '') {
        $parsed = ugfx_parse_icecast_data($xml);
        $preferred = ugfx_pick_preferred_source($parsed['sources'] ?? []);

        $title = trim((string)($preferred['title'] ?? ''));
        $artist = trim((string)($preferred['server_name'] ?? 'Underground FX AutoDJ'));
        if ($title !== '' && 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)($preferred['listeners'] ?? 0),
            'title' => $title,
            'artist' => $artist ?: 'AutoDJ',
            'mount' => (string)($preferred['mount'] ?? ($cfg['mount_auto'] ?: '/autodj')),
            'stream_url' => $playerUrls['preferred'],
            'public_stream_url' => $publicStream,
            'direct_stream_url' => $publicStream,
            'status' => 'LIVE'
        ];

        $icyTitle = ugfx_fetch_icy_title($publicStream);
        if ($icyTitle !== '') {
            $data['title'] = $icyTitle;
            if (strpos($icyTitle, ' - ') !== false) {
                list($artistPart, $titlePart) = array_map('trim', explode(' - ', $icyTitle, 2));
                if ($artistPart !== '') $data['artist'] = $artistPart;
                if ($titlePart !== '') $data['title'] = $titlePart;
            }
        }

        if ($data['title'] === '') {
            $xsl = ugfx_fetch_stats_xsl_html();
            if ($xsl !== '') {
                $xslParsed = ugfx_parse_stats_xsl_html($xsl);
                if (!empty($xslParsed['title'])) {
                    $data['title'] = $xslParsed['title'];
                    if (strpos($xslParsed['title'], ' - ') !== false) {
                        list($artistPart, $titlePart) = array_map('trim', explode(' - ', $xslParsed['title'], 2));
                        if ($artistPart !== '') $data['artist'] = $artistPart;
                        if ($titlePart !== '') $data['title'] = $titlePart;
                    }
                }
                if (!empty($xslParsed['listener_connections'])) {
                    $data['server_listeners'] = (int)$xslParsed['listener_connections'];
                }
                if (!empty($xslParsed['mount_listeners'])) {
                    $data['current_listeners'] = (int)$xslParsed['mount_listeners'];
                }
            }
        }

        if ($data['title'] === '') $data['title'] = 'Underground FX Live';
        if ($data['artist'] === '') $data['artist'] = 'AutoDJ';
        return $data;
    }

    $xsl = ugfx_fetch_stats_xsl_html();
    if ($xsl !== '') {
        $xslParsed = ugfx_parse_stats_xsl_html($xsl);
        $title = $xslParsed['title'];
        $artist = $xslParsed['server_name'] ?: 'Underground FX AutoDJ';
        if ($title !== '' && strpos($title, ' - ') !== false) {
            list($artistPart, $titlePart) = array_map('trim', explode(' - ', $title, 2));
            if ($artistPart !== '') $artist = $artistPart;
            if ($titlePart !== '') $title = $titlePart;
        }
        $fallback['server_listeners'] = (int)$xslParsed['listener_connections'];
        $fallback['current_listeners'] = (int)$xslParsed['mount_listeners'];
        $fallback['title'] = $title ?: 'Underground FX Live';
        $fallback['artist'] = $artist ?: 'AutoDJ';
    }

    $icyTitle = ugfx_fetch_icy_title($publicStream);
    if ($icyTitle !== '') {
        $fallback['title'] = $icyTitle;
        if (strpos($icyTitle, ' - ') !== false) {
            list($artistPart, $titlePart) = array_map('trim', explode(' - ', $icyTitle, 2));
            if ($artistPart !== '') $fallback['artist'] = $artistPart;
            if ($titlePart !== '') $fallback['title'] = $titlePart;
        }
    }

    return $fallback;
}
}

if (!function_exists('ugfx_read_stream_cache')) {
function ugfx_read_stream_cache(): ?array {
    $cfg = ugfx_get_stream_config();
    $cacheFile = $cfg['cache_file'];
    $cacheTtl = (int)($cfg['cache_ttl'] ?? 15);
    if (!is_file($cacheFile)) return null;
    if (time() - (int)filemtime($cacheFile) > $cacheTtl) return null;
    $raw = @file_get_contents($cacheFile);
    $data = $raw ? json_decode($raw, true) : null;
    return is_array($data) ? $data : null;
}
}

if (!function_exists('ugfx_read_stale_stream_cache')) {
function ugfx_read_stale_stream_cache(): ?array {
    $cfg = ugfx_get_stream_config();
    $cacheFile = $cfg['cache_file'];
    if (!is_file($cacheFile)) return null;
    $raw = @file_get_contents($cacheFile);
    $data = $raw ? json_decode($raw, true) : null;
    return is_array($data) ? $data : null;
}
}

if (!function_exists('ugfx_write_stream_cache')) {
function ugfx_write_stream_cache(array $data): void {
    $cfg = ugfx_get_stream_config();
    $cacheFile = $cfg['cache_file'];
    $dir = dirname($cacheFile);
    if (!is_dir($dir)) @mkdir($dir, 0755, true);
    @file_put_contents($cacheFile, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), LOCK_EX);
}
}
