<?php
declare(strict_types=1);

/**
 * functional/audio/_boot.php
 * Відповідає за:
 * - підключення ядра (/includes/start.php)
 * - перевірку авторизації (з безпечним ?to= поверненням)
 * - CSRF (fallback, якщо в проєкті немає своїх функцій)
 * - локальні тексти UA/RU/EN для модуля аудіо
 * - константи квот/лімітів та helper-и
 *
 * ВАЖЛИВО:
 * - НЕ переоголошуємо функції, які можуть існувати у /includes/helpers.php
 *   (is_post, post_str тощо) => все під function_exists().
 */

require_once __DIR__ . '/../../includes/start.php';

/* ===== Ensure $pdo / $me exist (don’t re-connect unnecessarily) ===== */
if (!isset($pdo) || !($pdo instanceof PDO)) {
    $pdo = db();
}
if (!isset($me) || !is_array($me)) {
    $me = current_user();
}

/* ===== Safe current path for ?to= (avoid open redirect) ===== */
if (!function_exists('audio_current_path')) {
    function audio_current_path(): string
    {
        $u = (string)($_SERVER['REQUEST_URI'] ?? '/');
        $u = str_replace(["\0", "\r", "\n"], '', $u);
        // if some proxy puts absolute URL, keep only path+query
        $p = parse_url($u);
        $path = (string)($p['path'] ?? '/');
        $q = isset($p['query']) && $p['query'] !== '' ? ('?' . $p['query']) : '';
        $out = $path . $q;
        if ($out === '' || $out[0] !== '/') $out = '/' . ltrim($out, '/');
        return $out;
    }
}

if (!$me) {
    $to = function_exists('current_uri') ? (string)current_uri() : audio_current_path();
    // ensure local path only
    if (!function_exists('safe_local_path')) {
        function safe_local_path(string $path, string $fallback = '/'): string
        {
            $path = trim(str_replace(["\0", "\r", "\n"], '', $path));
            if ($path === '') return $fallback;

            $p = parse_url($path);
            $pathOnly = (string)($p['path'] ?? '');
            $q = isset($p['query']) && $p['query'] !== '' ? ('?' . $p['query']) : '';
            $out = $pathOnly . $q;

            if ($out === '' || $out[0] !== '/') $out = '/' . ltrim($out, '/');
            if (str_contains($out, "\0")) return $fallback;
            return $out;
        }
    }
    $to = safe_local_path($to, '/');

    $login = '/login.php?to=' . urlencode($to);
    if (function_exists('redirect')) {
        redirect($login);
    }
    header('Location: ' . $login, true, 302);
    exit;
}

/* ===== Default: приватний модуль => не індексуємо (можна перевизначити в сторінці) ===== */
if (!isset($meta_robots)) {
    $meta_robots = 'noindex, nofollow, noarchive, nosnippet';
}
if (!headers_sent()) {
    header('X-Robots-Tag: ' . $meta_robots, true);
    header('X-Content-Type-Options: nosniff', true);
}

/* ===== Safe h() fallback ===== */
if (!function_exists('h')) {
    function h(?string $s): string
    {
        return htmlspecialchars((string)$s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
    }
}

/* ===== Flash fallback (optional) ===== */
if (!function_exists('flash_set')) {
    function flash_set(string $key, string $msg): void
    {
        if (session_status() !== PHP_SESSION_ACTIVE && !headers_sent()) {
            session_start();
        }
        $_SESSION['_flash'][$key] = $msg;
    }
}
if (!function_exists('flash_get')) {
    function flash_get(string $key): ?string
    {
        if (session_status() !== PHP_SESSION_ACTIVE && !headers_sent()) {
            session_start();
        }
        if (!isset($_SESSION['_flash'][$key])) return null;
        $v = (string)$_SESSION['_flash'][$key];
        unset($_SESSION['_flash'][$key]);
        return $v;
    }
}

/* ===== CSRF fallback ===== */
if (!function_exists('csrf_token')) {
    function csrf_token(): string
    {
        if (session_status() !== PHP_SESSION_ACTIVE && !headers_sent()) {
            session_start();
        }
        if (empty($_SESSION['_csrf'])) {
            $_SESSION['_csrf'] = bin2hex(random_bytes(32));
        }
        return (string)$_SESSION['_csrf'];
    }
}
if (!function_exists('csrf_check')) {
    function csrf_check(?string $token): bool
    {
        if (session_status() !== PHP_SESSION_ACTIVE && !headers_sent()) {
            session_start();
        }
        return is_string($token)
            && $token !== ''
            && isset($_SESSION['_csrf'])
            && hash_equals((string)$_SESSION['_csrf'], $token);
    }
}

/* ===== Small helpers (guarded to avoid redeclare) ===== */
if (!function_exists('is_post')) {
    function is_post(): bool
    {
        return (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST');
    }
}

if (!function_exists('post_str')) {
    function post_str(string $k, string $default = ''): string
    {
        $v = $_POST[$k] ?? $default;
        if (is_array($v)) return $default;
        if (!is_scalar($v) && $v !== null) return $default;
        return trim((string)$v);
    }
}

if (!function_exists('get_str')) {
    function get_str(string $k, string $default = ''): string
    {
        $v = $_GET[$k] ?? $default;
        if (is_array($v)) return $default;
        if (!is_scalar($v) && $v !== null) return $default;
        return trim((string)$v);
    }
}

if (!function_exists('get_int')) {
    function get_int(string $k, int $default = 0): int
    {
        $v = $_GET[$k] ?? $default;
        if (is_array($v)) return $default;
        if (!is_scalar($v) && $v !== null) return $default;
        return (int)$v;
    }
}

if (!function_exists('post_int')) {
    function post_int(string $k, int $default = 0): int
    {
        $v = $_POST[$k] ?? $default;
        if (is_array($v)) return $default;
        if (!is_scalar($v) && $v !== null) return $default;
        return (int)$v;
    }
}

if (!function_exists('redirect')) {
    function redirect(string $to, int $code = 303): void
    {
        header('Location: ' . $to, true, $code);
        exit;
    }
}

/* ===== Language for audio module ===== */
if (!function_exists('audio_lang')) {
    function audio_lang(): string
    {
        if (function_exists('current_lang')) {
            $lang = strtolower((string)current_lang());
        } else {
            if (session_status() !== PHP_SESSION_ACTIVE && !headers_sent()) {
                session_start();
            }
            $lang = strtolower((string)($_SESSION['lang'] ?? 'uk'));
        }

        if (!in_array($lang, ['uk', 'ru', 'en'], true)) $lang = 'uk';
        return $lang;
    }
}

/* ===== Module i18n ===== */
if (!function_exists('audio_t')) {
    function audio_t(string $key): string
    {
        static $dict = null;
        if ($dict === null) {
            $dict = [
                'uk' => [
                    'audio' => 'Аудіо',
                    'my_music' => 'Моя музика',
                    'audio_app' => 'Audio App (музика не зупиняється)',
                    'upload_tracks' => 'Завантажити пісні',
                    'select_files' => 'Обрати файли',
                    'upload' => 'Завантажити',
                    'limit_per_file' => 'Ліміт одного файлу',
                    'quota' => 'Квота',
                    'used' => 'Використано',
                    'tracks' => 'Пісні',
                    'playlists' => 'Плейлисти',
                    'create_playlist' => 'Створити плейлист',
                    'playlist_title' => 'Назва плейлиста',
                    'create' => 'Створити',
                    'open' => 'Відкрити',
                    'delete' => 'Видалити',
                    'save' => 'Зберегти',
                    'title' => 'Назва',
                    'artist' => 'Виконавець',
                    'actions' => 'Дії',
                    'add_to_playlist' => 'Додати в плейлист',
                    'choose_playlist' => 'Обрати плейлист',
                    'added' => 'Додано',
                    'back' => 'Назад',
                    'play_all' => 'Відтворити все',
                    'play_playlist' => 'Відтворити плейлист',
                    'remove' => 'Прибрати',
                    'site_inside' => 'Сайт всередині',
                ],
                'ru' => [
                    'audio' => 'Аудио',
                    'my_music' => 'Моя музыка',
                    'audio_app' => 'Audio App (музыка не останавливается)',
                    'upload_tracks' => 'Загрузить песни',
                    'select_files' => 'Выбрать файлы',
                    'upload' => 'Загрузить',
                    'limit_per_file' => 'Лимит одного файла',
                    'quota' => 'Квота',
                    'used' => 'Использовано',
                    'tracks' => 'Песни',
                    'playlists' => 'Плейлисты',
                    'create_playlist' => 'Создать плейлист',
                    'playlist_title' => 'Название плейлиста',
                    'create' => 'Создать',
                    'open' => 'Открыть',
                    'delete' => 'Удалить',
                    'save' => 'Сохранить',
                    'title' => 'Название',
                    'artist' => 'Исполнитель',
                    'actions' => 'Действия',
                    'add_to_playlist' => 'Добавить в плейлист',
                    'choose_playlist' => 'Выбрать плейлист',
                    'added' => 'Добавлено',
                    'back' => 'Назад',
                    'play_all' => 'Воспроизвести всё',
                    'play_playlist' => 'Воспроизвести плейлист',
                    'remove' => 'Убрать',
                    'site_inside' => 'Сайт внутри',
                ],
                'en' => [
                    'audio' => 'Audio',
                    'my_music' => 'My music',
                    'audio_app' => 'Audio App (music keeps playing)',
                    'upload_tracks' => 'Upload tracks',
                    'select_files' => 'Select files',
                    'upload' => 'Upload',
                    'limit_per_file' => 'Per-file limit',
                    'quota' => 'Quota',
                    'used' => 'Used',
                    'tracks' => 'Tracks',
                    'playlists' => 'Playlists',
                    'create_playlist' => 'Create playlist',
                    'playlist_title' => 'Playlist title',
                    'create' => 'Create',
                    'open' => 'Open',
                    'delete' => 'Delete',
                    'save' => 'Save',
                    'title' => 'Title',
                    'artist' => 'Artist',
                    'actions' => 'Actions',
                    'add_to_playlist' => 'Add to playlist',
                    'choose_playlist' => 'Choose playlist',
                    'added' => 'Added',
                    'back' => 'Back',
                    'play_all' => 'Play all',
                    'play_playlist' => 'Play playlist',
                    'remove' => 'Remove',
                    'site_inside' => 'Site inside',
                ],
            ];
        }

        $L = audio_lang();
        return $dict[$L][$key] ?? $dict['uk'][$key] ?? $key;
    }
}

/* ===== Limits ===== */
if (!function_exists('audio_quota_bytes')) {
    function audio_quota_bytes(): int
    {
        return 5 * 1024 * 1024 * 1024; // 5GB
    }
}
if (!function_exists('audio_max_file_bytes')) {
    function audio_max_file_bytes(): int
    {
        return 25 * 1024 * 1024; // 25MB
    }
}

if (!function_exists('audio_used_bytes')) {
    function audio_used_bytes(PDO $pdo, int $userId): int
    {
        $st = $pdo->prepare("SELECT COALESCE(SUM(size_bytes),0) FROM audio_tracks WHERE user_id=?");
        $st->execute([$userId]);
        return (int)$st->fetchColumn();
    }
}

if (!function_exists('audio_fmt_bytes')) {
    function audio_fmt_bytes(int $b): string
    {
        $u = ['B', 'KB', 'MB', 'GB', 'TB'];
        $i = 0;
        $v = (float)$b;
        $max = count($u) - 1;
        while ($v >= 1024 && $i < $max) {
            $v /= 1024;
            $i++;
        }
        return rtrim(rtrim(number_format($v, 2, '.', ''), '0'), '.') . ' ' . $u[$i];
    }
}

/* ===== paths ===== */
if (!function_exists('audio_site_root_dir')) {
    function audio_site_root_dir(): string
    {
        $root = realpath(__DIR__ . '/../../');
        return $root ?: (__DIR__ . '/../../');
    }
}

/**
 * Абсолютний корінь upload-сховища (для безпечної перевірки в stream.php).
 * Повертає .../upload (або fallback шлях).
 */
if (!function_exists('audio_storage_root_abs')) {
    function audio_storage_root_abs(): string
    {
        $p = realpath(audio_site_root_dir() . '/upload');
        return $p ?: (rtrim(audio_site_root_dir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'upload');
    }
}

if (!function_exists('audio_safe_username')) {
    function audio_safe_username(array $me): string
    {
        $username = (string)($me['username'] ?? 'user');
        $username = strtolower($username);
        $username = preg_replace('~[^a-z0-9_\-\.]+~', '', $username) ?? '';
        $username = trim($username, ". \t\n\r\0\x0B");
        while (str_contains($username, '..')) {
            $username = str_replace('..', '.', $username);
        }
        if ($username === '' || $username[0] === '.') $username = 'user';
        if (strlen($username) > 64) $username = substr($username, 0, 64);
        return $username;
    }
}

if (!function_exists('audio_user_music_dir_rel')) {
    function audio_user_music_dir_rel(array $me): string
    {
        $username = audio_safe_username($me);
        return '/upload/' . $username . '/music';
    }
}

if (!function_exists('audio_is_safe_relpath')) {
    function audio_is_safe_relpath(string $relPath): bool
    {
        $relPath = str_replace(["\0", "\r", "\n"], '', $relPath);
        $relPath = '/' . ltrim($relPath, '/');
        if (str_contains($relPath, '\\')) return false;
        if (preg_match('~(^|/)\.\.(/|$)~', $relPath)) return false;
        return true;
    }
}

if (!function_exists('audio_rel_to_abs')) {
    function audio_rel_to_abs(string $relPath): string
    {
        $relPath = '/' . ltrim(str_replace(["\0", "\r", "\n"], '', $relPath), '/');
        if (!audio_is_safe_relpath($relPath)) {
            return rtrim(audio_site_root_dir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
        }
        return rtrim(audio_site_root_dir(), DIRECTORY_SEPARATOR) . str_replace('/', DIRECTORY_SEPARATOR, $relPath);
    }
}