/**
 * Ensure the screenshot-renderer (`@napi-rs/canvas`) has CJK / Latin / emoji
 * fonts available. Downloads missing categories from GitHub release
 * artifacts to `~/.botmux/fonts/` so registration (`GlobalFonts.registerFromPath`)
 * can find them at runtime.
 *
 * macOS is skipped entirely — PingFang + Menlo + Apple Color Emoji are
 * preinstalled.
 *
 * Failures are NOT fatal: missing fonts only degrade the screenshot rendered
 * for Lark (CJK becomes tofu, emoji becomes monochrome). The daemon should
 * still come up. Tmux is the load-bearing dep, fonts are nice-to-have.
 */
import { existsSync, mkdirSync, createWriteStream, statSync, unlinkSync, renameSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { get as httpsGet } from 'node:https';
import { detectPlatform } from './detect-platform.js';
const FONT_DIR = join(homedir(), '.botmux', 'fonts');
/** Download targets — pinned to specific release tags so the URLs don't rot.
 *
 *  Sources (all permissive licenses, GitHub-hosted):
 *  - notofonts/noto-cjk @ Sans2.004 (Mono variant) — OFL
 *  - JetBrains/JetBrainsMono @ v2.304 — Apache 2.0 (replaces DejaVu since
 *    DejaVu only ships .tar.bz2 release artifacts, not individual TTFs)
 *  - googlefonts/noto-emoji @ v2.047 — OFL
 */
const FONT_SPECS = [
    {
        category: 'CJK',
        files: [
            {
                name: 'NotoSansMonoCJKsc-Regular.otf',
                url: 'https://github.com/notofonts/noto-cjk/raw/Sans2.004/Sans/Mono/NotoSansMonoCJKsc-Regular.otf',
                minBytes: 1_000_000,
            },
            {
                name: 'NotoSansMonoCJKsc-Bold.otf',
                url: 'https://github.com/notofonts/noto-cjk/raw/Sans2.004/Sans/Mono/NotoSansMonoCJKsc-Bold.otf',
                minBytes: 1_000_000,
            },
        ],
        systemPaths: [
            '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc',
            '/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc',
            '/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc',
            '/usr/share/fonts/opentype/noto/NotoSansMonoCJK-Regular.ttc',
        ],
    },
    {
        category: 'Latin',
        files: [
            {
                name: 'JetBrainsMono-Regular.ttf',
                url: 'https://github.com/JetBrains/JetBrainsMono/raw/v2.304/fonts/ttf/JetBrainsMono-Regular.ttf',
                minBytes: 100_000,
            },
            {
                name: 'JetBrainsMono-Bold.ttf',
                url: 'https://github.com/JetBrains/JetBrainsMono/raw/v2.304/fonts/ttf/JetBrainsMono-Bold.ttf',
                minBytes: 100_000,
            },
        ],
        systemPaths: [
            '/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf',
            '/usr/share/fonts/dejavu/DejaVuSansMono.ttf',
            '/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf',
            '/usr/share/fonts/liberation/LiberationMono-Regular.ttf',
            '/usr/share/fonts/truetype/jetbrains-mono/JetBrainsMono-Regular.ttf',
        ],
    },
    {
        category: 'Emoji',
        files: [
            {
                name: 'NotoColorEmoji.ttf',
                url: 'https://github.com/googlefonts/noto-emoji/raw/v2.047/fonts/NotoColorEmoji.ttf',
                minBytes: 5_000_000,
            },
        ],
        systemPaths: [
            '/usr/share/fonts/truetype/noto/NotoColorEmoji.ttf',
            '/usr/share/fonts/noto/NotoColorEmoji.ttf',
            '/usr/share/fonts/google-noto-emoji/NotoColorEmoji.ttf',
        ],
    },
];
/** Public: paths the screenshot-renderer should also probe. */
export function botmuxFontDir() {
    return FONT_DIR;
}
function categoryAlreadyOk(spec) {
    // 1. System path present?
    if (spec.systemPaths.some(p => existsSync(p)))
        return true;
    // 2. We already downloaded it on a prior run?
    return spec.files.every(f => {
        const p = join(FONT_DIR, f.name);
        if (!existsSync(p))
            return false;
        try {
            return statSync(p).size >= f.minBytes;
        }
        catch {
            return false;
        }
    });
}
/** Download a URL to disk, following redirects (GitHub raw → CDN).
 *  All FONT_SPECS URLs are https, so we don't bother with an http fallback.
 *  Hard timeout (default 60s) covers connect + transfer; on expiry the
 *  request is destroyed and the partial file is unlinked. */
function downloadFile(url, destPath, timeoutMs = 60_000) {
    return new Promise((resolve, reject) => {
        const tmp = destPath + '.part';
        let settled = false;
        let activeReq = null;
        const cleanup = () => {
            try {
                unlinkSync(tmp);
            }
            catch { /* may not exist */ }
        };
        const finish = (err) => {
            if (settled)
                return;
            settled = true;
            clearTimeout(timer);
            if (activeReq)
                try {
                    activeReq.destroy();
                }
                catch { /* ignore */ }
            if (err) {
                cleanup();
                reject(err);
            }
            else
                resolve();
        };
        const timer = setTimeout(() => finish(new Error(`下载超时 (${timeoutMs}ms): ${url}`)), timeoutMs);
        const followRedirect = (current, hops) => {
            if (hops > 5)
                return finish(new Error(`太多重定向: ${url}`));
            const u = new URL(current);
            if (u.protocol !== 'https:')
                return finish(new Error(`仅支持 https://, got ${u.protocol} for ${current}`));
            activeReq = httpsGet(u, { headers: { 'user-agent': 'botmux-font-installer' } }, (res) => {
                if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
                    res.resume();
                    followRedirect(new URL(res.headers.location, u).toString(), hops + 1);
                    return;
                }
                if (res.statusCode !== 200) {
                    res.resume();
                    return finish(new Error(`HTTP ${res.statusCode} for ${current}`));
                }
                const out = createWriteStream(tmp);
                res.pipe(out);
                out.on('error', (err) => finish(err));
                out.on('finish', () => {
                    out.close(() => {
                        try {
                            renameSync(tmp, destPath);
                            finish();
                        }
                        catch (err) {
                            finish(err);
                        }
                    });
                });
            });
            activeReq.on('error', (err) => finish(err));
        };
        followRedirect(url, 0);
    });
}
async function downloadCategory(spec) {
    if (!existsSync(FONT_DIR))
        mkdirSync(FONT_DIR, { recursive: true });
    for (const f of spec.files) {
        const dest = join(FONT_DIR, f.name);
        // Skip if already present and big enough.
        try {
            if (existsSync(dest) && statSync(dest).size >= f.minBytes)
                continue;
        }
        catch { /* fall through to redownload */ }
        console.log(`   下载 ${spec.category}: ${f.name} ...`);
        await downloadFile(f.url, dest);
        const sz = statSync(dest).size;
        if (sz < f.minBytes) {
            try {
                unlinkSync(dest);
            }
            catch { /* ignore */ }
            throw new Error(`${f.name} 下载完毕但大小异常 (${sz} < ${f.minBytes})`);
        }
    }
}
export async function ensureFonts(info) {
    const platform = info ?? detectPlatform();
    const result = { fontDir: FONT_DIR, ready: [], failed: [] };
    // macOS: skip — system fonts cover everything we need.
    if (platform.os === 'darwin') {
        result.ready.push('CJK', 'Latin', 'Emoji');
        return result;
    }
    for (const spec of FONT_SPECS) {
        if (categoryAlreadyOk(spec)) {
            result.ready.push(spec.category);
            continue;
        }
        try {
            await downloadCategory(spec);
            result.ready.push(spec.category);
        }
        catch (err) {
            console.warn(`⚠️  字体下载失败 [${spec.category}]: ${err?.message ?? err}`);
            result.failed.push(spec.category);
        }
    }
    return result;
}
//# sourceMappingURL=ensure-fonts.js.map