<?php
declare(strict_types=1);

/**
 * 前台模版：载入 fate/templates/&lt;FATE_TEMPLATE&gt;/home.php，缺档时退回 default。
 * Google AdSense：default／minimal 的 partials/head.php 皆須呼叫 fate_template_render_adsense_head()。
 */

function fate_template_root(): string
{
    return dirname(__DIR__) . DIRECTORY_SEPARATOR . 'templates';
}

function fate_template_active_id(): string
{
    return defined('FATE_TEMPLATE') ? (string) FATE_TEMPLATE : 'default';
}

function fate_is_dcinside_theme(): bool
{
    return fate_template_active_id() === 'dcinside';
}

function fate_is_minimal_theme(): bool
{
    return fate_template_active_id() === 'minimal';
}

/**
 * 解析目前模版 partial（支援 $fateTemplatePartialsDir 覆寫，缺檔退回 default）。
 */
function fate_template_theme_partial(string $file): string
{
    global $fateTemplatePartialsDir;
    $candidates = [];
    if (isset($fateTemplatePartialsDir) && is_string($fateTemplatePartialsDir) && $fateTemplatePartialsDir !== '') {
        $candidates[] = rtrim($fateTemplatePartialsDir, '/\\') . DIRECTORY_SEPARATOR . $file;
    }
    $root = fate_template_root();
    $active = $root . DIRECTORY_SEPARATOR . fate_template_active_id() . DIRECTORY_SEPARATOR . 'partials' . DIRECTORY_SEPARATOR . $file;
    $candidates[] = $active;
    $candidates[] = $root . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR . 'partials' . DIRECTORY_SEPARATOR . $file;
    foreach ($candidates as $path) {
        if (is_file($path)) {
            return $path;
        }
    }

    throw new RuntimeException('找不到模版 partial：' . $file);
}

/** @return list<string> 相對於站台根目錄的 CSS 路徑 */
function fate_theme_extra_stylesheets(): array
{
    $sheets = fate_template_discover_stylesheets();
    if ($sheets !== []) {
        return $sheets;
    }

    return [];
}

function fate_theme_html_class(): string
{
    $manifest = fate_template_read_manifest();
    if ($manifest['html_class'] !== '') {
        return $manifest['html_class'];
    }

    return '';
}

function fate_theme_footer_variant(): string
{
    $manifest = fate_template_read_manifest();
    if (in_array($manifest['footer_variant'], ['dark', 'light'], true)) {
        return $manifest['footer_variant'];
    }

    return 'dark';
}

/**
 * 解析模版 partial 路徑（先目前模版，再退回 default）。
 */
function fate_template_resolve_partial_path(string $name, ?string $templateId = null): string
{
    $name = trim($name);
    if ($name === '' || preg_match('/^[a-z0-9_-]{1,32}$/', $name) !== 1) {
        throw new InvalidArgumentException('invalid template partial name');
    }
    $root = fate_template_root();
    foreach ([$templateId ?? fate_template_active_id(), 'default'] as $tid) {
        $path = $root . DIRECTORY_SEPARATOR . $tid . DIRECTORY_SEPARATOR . 'partials' . DIRECTORY_SEPARATOR . $name . '.php';
        if (is_file($path)) {
            return $path;
        }
    }
    throw new RuntimeException('找不到模版 partial：' . $name);
}

/**
 * 載入 partial。注意：在函式 scope 執行，無法讀取 fate_render_home/store 的 extract 變數。
 * 需要 $fatePageHitCount、$fatePageTitle 等請在模版內改為 require partials/xxx.php（見 home.php、store.php）。
 */
function fate_template_require_partial(string $name, ?string $templateId = null): void
{
    require fate_template_resolve_partial_path($name, $templateId);
}

/** 輸出 Google AdSense 自動廣告 script（兩套模版 head 共用） */
function fate_template_render_adsense_head(): void
{
    if (!function_exists('fate_adsense_head_html')) {
        require_once __DIR__ . DIRECTORY_SEPARATOR . 'fate_adsense.php';
    }
    echo fate_adsense_head_html();
}

/** @return list<string> */
function fate_installed_template_ids(): array
{
    $root = fate_template_root();
    $out = [];
    if (!is_dir($root)) {
        return ['default'];
    }
    foreach (scandir($root, SCANDIR_SORT_ASCENDING) ?: [] as $name) {
        if ($name === '.' || $name === '..' || str_starts_with($name, '_')) {
            continue;
        }
        $dir = $root . DIRECTORY_SEPARATOR . $name;
        if (!is_dir($dir)) {
            continue;
        }
        if (is_file($dir . DIRECTORY_SEPARATOR . 'home.php')) {
            $out[] = $name;
        }
    }
    return $out !== [] ? $out : ['default'];
}

/** @return array<string, array{file:string, label:string, required:bool}> */
function fate_template_page_definitions(): array
{
    return [
        'home' => ['file' => 'home.php', 'label' => '首頁', 'required' => true],
        'store' => ['file' => 'store.php', 'label' => '店家詳情', 'required' => false],
        'member_profile' => ['file' => 'member_profile.php', 'label' => '我的帳號', 'required' => false],
        'blog' => ['file' => 'blog.php', 'label' => '公告／文章', 'required' => false],
        'blog_post' => ['file' => 'blog_post.php', 'label' => '文章內頁', 'required' => false],
        'login' => ['file' => 'login.php', 'label' => '登入', 'required' => false],
        'register' => ['file' => 'register.php', 'label' => '註冊', 'required' => false],
    ];
}

function fate_template_manifest_path(string $templateId): string
{
    return fate_template_root() . DIRECTORY_SEPARATOR . $templateId . DIRECTORY_SEPARATOR . 'theme.json';
}

/**
 * 讀取模版 manifest（theme.json）；缺檔時回傳合理預設。
 *
 * @return array{
 *   id:string,
 *   title:string,
 *   description:string,
 *   html_class:string,
 *   footer_variant:string,
 *   stylesheets:list<string>,
 *   has_manifest:bool
 * }
 */
function fate_template_read_manifest(?string $templateId = null): array
{
    $id = $templateId ?? fate_template_active_id();
    $builtInTitles = [
        'default' => '預設深色卡片',
        'minimal' => '簡約淺色全站',
        'dcinside' => 'DC Inside 風格',
    ];
    $builtInDescriptions = [
        'default' => '完整 default 模版：首頁、店家、會員、登入／註冊',
        'minimal' => '獨立簡約排版，含首頁／店家／會員／登入／註冊',
        'dcinside' => '沿用 default 版面，淺色 DC 風配色',
    ];

    $out = [
        'id' => $id,
        'title' => $builtInTitles[$id] ?? $id,
        'description' => $builtInDescriptions[$id] ?? '',
        'html_class' => '',
        'footer_variant' => 'dark',
        'stylesheets' => [],
        'has_manifest' => false,
    ];

    $manifestPath = fate_template_manifest_path($id);
    if (is_file($manifestPath)) {
        $raw = file_get_contents($manifestPath);
        $json = is_string($raw) ? json_decode($raw, true) : null;
        if (is_array($json)) {
            $out['has_manifest'] = true;
            if (isset($json['title']) && is_string($json['title']) && trim($json['title']) !== '') {
                $out['title'] = trim($json['title']);
            }
            if (isset($json['description']) && is_string($json['description'])) {
                $out['description'] = trim($json['description']);
            }
            if (isset($json['html_class']) && is_string($json['html_class'])) {
                $out['html_class'] = trim($json['html_class']);
            }
            $fv = isset($json['footer_variant']) ? strtolower(trim((string) $json['footer_variant'])) : '';
            if (in_array($fv, ['dark', 'light'], true)) {
                $out['footer_variant'] = $fv;
            }
            if (isset($json['stylesheets']) && is_array($json['stylesheets'])) {
                foreach ($json['stylesheets'] as $sheet) {
                    if (!is_string($sheet)) {
                        continue;
                    }
                    $sheet = trim($sheet);
                    if ($sheet === '') {
                        continue;
                    }
                    if (str_starts_with($sheet, './')) {
                        $out['stylesheets'][] = $sheet;
                        continue;
                    }
                    $out['stylesheets'][] = './templates/' . $id . '/' . ltrim(str_replace('\\', '/', $sheet), '/');
                }
            }
        }
    }

    $autoThemeCss = fate_template_root() . DIRECTORY_SEPARATOR . $id . DIRECTORY_SEPARATOR . 'theme.css';
    if (is_file($autoThemeCss)) {
        $autoHref = './templates/' . $id . '/theme.css';
        if (!in_array($autoHref, $out['stylesheets'], true)) {
            $out['stylesheets'][] = $autoHref;
        }
    }

    if ($out['stylesheets'] === [] && $id === 'dcinside') {
        $out['stylesheets'] = ['./static/dcinside-theme.css'];
        $out['html_class'] = $out['html_class'] !== '' ? $out['html_class'] : 'fate-theme-dci';
        $out['footer_variant'] = 'light';
    } elseif ($out['stylesheets'] === [] && $id === 'minimal') {
        $out['stylesheets'] = ['./static/minimal-theme.css'];
        $out['html_class'] = $out['html_class'] !== '' ? $out['html_class'] : 'fate-theme-minimal';
        $out['footer_variant'] = 'light';
    }

    return $out;
}

/**
 * 後台／除錯：模版完整性與 manifest 摘要。
 *
 * @return array{
 *   id:string,
 *   title:string,
 *   description:string,
 *   html_class:string,
 *   footer_variant:string,
 *   stylesheets:list<string>,
 *   has_manifest:bool,
 *   pages:list<array{key:string, label:string, file:string, present:bool, fallback:bool, required:bool}>,
 *   installable:bool
 * }
 */
function fate_template_inspect(string $templateId): array
{
    $manifest = fate_template_read_manifest($templateId);
    $dir = fate_template_root() . DIRECTORY_SEPARATOR . $templateId;
    $pages = [];
    foreach (fate_template_page_definitions() as $key => $def) {
        $present = is_file($dir . DIRECTORY_SEPARATOR . $def['file']);
        $pages[] = [
            'key' => $key,
            'label' => $def['label'],
            'file' => $def['file'],
            'present' => $present,
            'fallback' => !$def['required'] && !$present,
            'required' => $def['required'],
        ];
    }

    return array_merge($manifest, [
        'pages' => $pages,
        'installable' => is_file($dir . DIRECTORY_SEPARATOR . 'home.php'),
    ]);
}

/** @return list<string> */
function fate_template_discover_stylesheets(?string $templateId = null): array
{
    return fate_template_read_manifest($templateId)['stylesheets'];
}

function fate_resolve_home_template(): string
{
    $root = fate_template_root();
    $id = defined('FATE_TEMPLATE') ? FATE_TEMPLATE : 'default';
    $primary = $root . DIRECTORY_SEPARATOR . $id . DIRECTORY_SEPARATOR . 'home.php';
    if (is_file($primary)) {
        return $primary;
    }
    $fallback = $root . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR . 'home.php';
    if (is_file($fallback)) {
        return $fallback;
    }
    throw new RuntimeException('找不到前台模版：templates/default/home.php');
}

/**
 * 全站統一頁尾樣式表（相對於站台根目錄之路徑前綴，討論區用 ../）
 */
function fate_site_footer_stylesheet_tag(string $hrefPrefix = './'): string
{
    $cssFs = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'static' . DIRECTORY_SEPARATOR . 'fate-site-footer.css';
    $ver = is_file($cssFs) ? (string) filemtime($cssFs) : '1';
    $href = rtrim($hrefPrefix, '/') . '/static/fate-site-footer.css?v=' . rawurlencode($ver);

    return '<link rel="stylesheet" href="' . htmlspecialchars($href, ENT_QUOTES, 'UTF-8') . '">';
}

function fate_social_links_stylesheet_tag(string $hrefPrefix = './'): string
{
    $cssFs = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'static' . DIRECTORY_SEPARATOR . 'fate-social-links.css';
    $ver = is_file($cssFs) ? (string) filemtime($cssFs) : '1';
    $href = rtrim($hrefPrefix, '/') . '/static/fate-social-links.css?v=' . rawurlencode($ver);

    return '<link rel="stylesheet" href="' . htmlspecialchars($href, ENT_QUOTES, 'UTF-8') . '">';
}

/**
 * 標準頁腳（XSpa/CC 宣告 + 瀏覽計數）。所有模版 partials/footer.php 務必傳入計數相關變數。
 *
 * @param 'dark'|'light' $visualVariant 深色／淺色版型對應 CSS（default 模版用 dark，minimal 用 light）
 * @param array<string,mixed> $footerVars 須至少含 fatePageHitCount（由 footer.php 使用 compact('fatePageHitCount')）
 */
function fate_template_footer_render(string $visualVariant = 'dark', array $footerVars = []): void
{
    extract($footerVars, EXTR_SKIP);
    $fateCounterFooterVariant = ($visualVariant === 'light') ? 'light' : 'dark';
    $fateFooterLayout = ($visualVariant === 'light') ? 'minimal' : 'default';
    $partialsDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'partials';
    require $partialsDir . DIRECTORY_SEPARATOR . 'site_social_links.php';
    require $partialsDir . DIRECTORY_SEPARATOR . 'site_footer.php';
}

/**
 * 載入目前模版 home.php。模版結尾須含標準頁腳（require partials/footer.php；footer 內會呼叫 fate_template_footer_render 並傳入 compact('fatePageHitCount')）。
 *
 * @param array<string,mixed> $vars
 */
function fate_render_home(array $vars): void
{
    extract($vars, EXTR_SKIP);
    include fate_resolve_home_template();
}

function fate_resolve_store_template(): string
{
    $root = fate_template_root();
    $id = defined('FATE_TEMPLATE') ? FATE_TEMPLATE : 'default';
    $primary = $root . DIRECTORY_SEPARATOR . $id . DIRECTORY_SEPARATOR . 'store.php';
    if (is_file($primary)) {
        return $primary;
    }
    $fallback = $root . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR . 'store.php';
    if (is_file($fallback)) {
        return $fallback;
    }
    throw new RuntimeException('找不到前台模版：templates/default/store.php');
}

/**
 * @param array<string,mixed> $vars
 */
function fate_render_store(array $vars): void
{
    extract($vars, EXTR_SKIP);
    include fate_resolve_store_template();
}

function fate_resolve_member_profile_template(): string
{
    $root = fate_template_root();
    $id = defined('FATE_TEMPLATE') ? FATE_TEMPLATE : 'default';
    $primary = $root . DIRECTORY_SEPARATOR . $id . DIRECTORY_SEPARATOR . 'member_profile.php';
    if (is_file($primary)) {
        return $primary;
    }
    $fallback = $root . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR . 'member_profile.php';
    if (is_file($fallback)) {
        return $fallback;
    }
    throw new RuntimeException('找不到前台模版：templates/default/member_profile.php');
}

/**
 * @param array<string,mixed> $vars
 */
function fate_render_member_profile(array $vars): void
{
    extract($vars, EXTR_SKIP);
    include fate_resolve_member_profile_template();
}

function fate_resolve_login_template(): string
{
    $root = fate_template_root();
    $id = defined('FATE_TEMPLATE') ? FATE_TEMPLATE : 'default';
    $primary = $root . DIRECTORY_SEPARATOR . $id . DIRECTORY_SEPARATOR . 'login.php';
    if (is_file($primary)) {
        return $primary;
    }
    $fallback = $root . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR . 'login.php';
    if (is_file($fallback)) {
        return $fallback;
    }
    throw new RuntimeException('找不到前台模版：templates/default/login.php');
}

/** @param array<string,mixed> $vars */
function fate_render_login(array $vars): void
{
    extract($vars, EXTR_SKIP);
    include fate_resolve_login_template();
}

function fate_resolve_register_template(): string
{
    $root = fate_template_root();
    $id = defined('FATE_TEMPLATE') ? FATE_TEMPLATE : 'default';
    $primary = $root . DIRECTORY_SEPARATOR . $id . DIRECTORY_SEPARATOR . 'register.php';
    if (is_file($primary)) {
        return $primary;
    }
    $fallback = $root . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR . 'register.php';
    if (is_file($fallback)) {
        return $fallback;
    }
    throw new RuntimeException('找不到前台模版：templates/default/register.php');
}

/** @param array<string,mixed> $vars */
function fate_render_register(array $vars): void
{
    extract($vars, EXTR_SKIP);
    include fate_resolve_register_template();
}

function fate_resolve_blog_template(): string
{
    $root = fate_template_root();
    $id = defined('FATE_TEMPLATE') ? FATE_TEMPLATE : 'default';
    foreach ([$id, 'default'] as $tid) {
        $path = $root . DIRECTORY_SEPARATOR . $tid . DIRECTORY_SEPARATOR . 'blog.php';
        if (is_file($path)) {
            return $path;
        }
    }
    throw new RuntimeException('找不到前台模版：templates/default/blog.php');
}

/** @param array<string,mixed> $vars */
function fate_render_blog(array $vars): void
{
    extract($vars, EXTR_SKIP);
    include fate_resolve_blog_template();
}

function fate_resolve_blog_post_template(): string
{
    $root = fate_template_root();
    $id = defined('FATE_TEMPLATE') ? FATE_TEMPLATE : 'default';
    foreach ([$id, 'default'] as $tid) {
        $path = $root . DIRECTORY_SEPARATOR . $tid . DIRECTORY_SEPARATOR . 'blog_post.php';
        if (is_file($path)) {
            return $path;
        }
    }
    throw new RuntimeException('找不到前台模版：templates/default/blog_post.php');
}

/** @param array<string,mixed> $vars */
function fate_render_blog_post(array $vars): void
{
    extract($vars, EXTR_SKIP);
    include fate_resolve_blog_post_template();
}

function fate_resolve_masseur_weekly_template(): string
{
    $root = fate_template_root();
    $id = defined('FATE_TEMPLATE') ? FATE_TEMPLATE : 'default';
    foreach ([$id, 'default'] as $tid) {
        $path = $root . DIRECTORY_SEPARATOR . $tid . DIRECTORY_SEPARATOR . 'masseur_weekly.php';
        if (is_file($path)) {
            return $path;
        }
    }
    throw new RuntimeException('找不到前台模版：templates/default/masseur_weekly.php');
}

/** @param array<string,mixed> $vars */
function fate_render_masseur_weekly(array $vars): void
{
    extract($vars, EXTR_SKIP);
    include fate_resolve_masseur_weekly_template();
}
