<?php
// lib.php

// ルートの絶対パス（このフォルダ自身）
function base_dir(): string {
    static $b = null;
    if ($b === null) $b = realpath(__DIR__);
    return $b;
}

// HTMLエスケープ
function h(string $s): string {
    return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}

// 画像拡張子判定
function is_image_ext(string $path): bool {
    $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
    return in_array($ext, ['jpg','jpeg','png','gif','webp','bmp','svg','avif','ico']);
}

// ファイルサイズの人間向け表記
function file_size_human(int $bytes): string {
    $units = ['B','KB','MB','GB','TB'];
    $i = 0;
    while ($bytes >= 1024 && $i < count($units)-1) { $bytes /= 1024; $i++; }
    return sprintf('%s %s', ($i === 0 ? $bytes : number_format($bytes, 2)), $units[$i]);
}

// base_dir からの相対パス（先頭/なし）
function rel_from_full(string $full): string {
    $base = base_dir();
    return ltrim(str_replace('\\','/', substr($full, strlen($base))), '/');
}

// 同ディレクトリ内の兄弟ファイル（ソート済）
function siblings(string $full): array {
    $dir = dirname($full);
    if (!is_dir($dir)) return [[], null, null];
    $files = array_values(array_filter(scandir($dir), function($f) use ($dir){
        return $f !== '.' && $f !== '..' && is_file($dir.'/'.$f);
    }));
    natsort($files);
    $files = array_values($files);
    $name = basename($full);
    $idx = array_search($name, $files, true);
    $prev = ($idx !== false && $idx > 0) ? $files[$idx-1] : null;
    $next = ($idx !== false && $idx < count($files)-1) ? $files[$idx+1] : null;
    return [$files, $prev, $next];
}

// 安全なパス解決（base_dir 外のアクセスは拒否）
function resolve_request_path(?string $reqPath): array {
    $reqPath = ltrim($reqPath ?? '', '/');
    $full = realpath(base_dir() . '/' . $reqPath);
    if ($full === false) $full = base_dir() . '/' . $reqPath; // 未存在でも仮フルパス

    $baseReal = base_dir();
    $fullReal = realpath($full) ?: $full;
    if (strpos(str_replace('\\','/',$fullReal), str_replace('\\','/',$baseReal)) !== 0) {
        return ['ok'=>false,'reason'=>'out_of_base'];
    }
    return [
        'ok'      => true,
        'full'    => $full,
        'exists'  => file_exists($full),
        'is_file' => is_file($full),
        'is_dir'  => is_dir($full),
        'rel'     => rel_from_full($full),
        'req'     => $reqPath,
    ];
}

/* ===== 設置パス自動検出（どの階層でも編集不要） ===== */

// このアプリ（index.php がある場所）のURLベース（例：/contents）。環境変数 APP_BASE があれば優先。
function base_url(): string {
    if (!empty($_SERVER['APP_BASE'])) return rtrim($_SERVER['APP_BASE'], '/'); // 例: /viewer
    $dir = str_replace('\\','/', dirname($_SERVER['SCRIPT_NAME'] ?? ''));
    return rtrim($dir, '/'); // 例：/contents、ルートなら ''
}

// アプリ内URLを作る（先頭/不要。クエリは配列で渡す）
function u(string $path, array $qs = []): string {
    $base = base_url();
    $p = ($base === '' ? '' : $base) . '/' . ltrim($path, '/');
    if ($qs) {
        $q = http_build_query($qs);
        $p .= (strpos($p, '?') === false ? '?' : '&') . $q;
    }
    return $p;
}
function u_raw(string $rel): string  { return u($rel, ['raw'=>1]); }
function u_down(string $rel): string { return u($rel, ['download'=>1]); }

/* ===== 埋め込み判定（image/script/style/video/audio/font 等） ===== */
function is_embedded_request(): bool {
    $dest = $_SERVER['HTTP_SEC_FETCH_DEST'] ?? '';
    if ($dest !== '') {
        if (in_array($dest, ['image','script','style','video','audio','font','embed','object','track','iframe'], true)) {
            return true;
        }
        if ($dest === 'empty') { // XHR/fetch 等
            $accept = strtolower($_SERVER['HTTP_ACCEPT'] ?? '');
            if ($accept && (
                str_contains($accept, 'image/') ||
                str_contains($accept, 'text/css') ||
                str_contains($accept, 'application/javascript') ||
                str_contains($accept, 'text/javascript') ||
                str_contains($accept, 'font/') ||
                str_contains($accept, 'audio/') ||
                str_contains($accept, 'video/')
            )) return true;
        }
    }
    // Fallback：Accept で推定
    $accept = strtolower($_SERVER['HTTP_ACCEPT'] ?? '');
    if ($accept && !str_contains($accept, 'text/html')) {
        if (
            str_contains($accept, 'image/') ||
            str_contains($accept, 'text/css') ||
            str_contains($accept, 'application/javascript') ||
            str_contains($accept, 'text/javascript') ||
            str_contains($accept, 'font/') ||
            str_contains($accept, 'audio/') ||
            str_contains($accept, 'video/')
        ) return true;
    }
    return false;
}
