const test = require("node:test");
const assert = require("node:assert/strict");
const fs = require("fs");
const path = require("path");

const root = path.resolve(__dirname, "..");
const read = (file) => fs.readFileSync(path.join(root, file), "utf8");

test("backend secrets are loaded from environment variables", () => {
    const config = read("backend/config.php");
    assert.match(config, /DB_PASS/);
    assert.match(config, /STRIPE_SECRET_KEY/);
    assert.doesNotMatch(config, /player123456|44253422/);
});

test("device APIs require device authentication", () => {
    for (const file of ["backend/api/device.php", "backend/api/playlist.php", "backend/api/sync.php"]) {
        assert.match(read(file), /authenticate_device/);
    }
});

test("proxies require signed tokens and subscription access", () => {
    for (const file of ["backend/api/iptv_proxy.php", "backend/api/stream_proxy.php"]) {
        const source = read(file);
        assert.match(source, /device_from_signed_token/);
        assert.match(source, /require_active_device/);
        assert.match(source, /validate_proxy_url/);
        assert.match(source, /CURLOPT_RESOLVE/);
    }
});

test("legacy device claiming is disabled by default", () => {
    assert.match(read("backend/config.php"), /ALLOW_LEGACY_DEVICE_CLAIM', false/);
    assert.match(read("backend/lib/bootstrap.php"), /allow_legacy_device_claim/);
});

test("playlist writes enforce ownership and configured limits", () => {
    const source = read("backend/api/playlist.php");
    assert.match(source, /Playlist not found/);
    assert.match(source, /app\.max_playlists/);
    assert.doesNotMatch(source, /rowCount\(\) > 0/);
});

test("Tizen package declares required privileges", () => {
    const config = read("app/config.xml");
    for (const privilege of ["internet", "download", "network.get", "tv.inputdevice", "avplay"]) {
        assert.ok(config.includes(privilege), `missing ${privilege}`);
    }
});

test("EPG catch-up playback is wired into the live interface", () => {
    const source = read("app/js/app.js");
    const html = read("app/index.html");
    assert.match(source, /function buildCatchupUrl/);
    assert.match(source, /function playPreviousLiveProgram/);
    assert.match(html, /id="liveCatchupButton"/);
});

test("active app source has no shadowed top-level function declarations", () => {
    const source = read("app/js/app.js");
    const names = [...source.matchAll(/^    function\s+([A-Za-z0-9_]+)\s*\(/gm)].map((match) => match[1]);
    assert.equal(new Set(names).size, names.length);
});
