import fs from "node:fs/promises";
import { listChannelPlugins } from "../../channels/plugins/index.js";
import { parseLogLine } from "../../logging/parse-log-line.js";
import { getResolvedLoggerSettings } from "../../logging.js";
import { defaultRuntime } from "../../runtime.js";
import { theme } from "../../terminal/theme.js";
const DEFAULT_LIMIT = 200;
const MAX_BYTES = 1_000_000;
const getChannelSet = () => new Set([...listChannelPlugins().map((plugin) => plugin.id), "all"]);
function parseChannelFilter(raw) {
    const trimmed = raw?.trim().toLowerCase();
    if (!trimmed)
        return "all";
    return getChannelSet().has(trimmed) ? trimmed : "all";
}
function matchesChannel(line, channel) {
    if (channel === "all")
        return true;
    const needle = `gateway/channels/${channel}`;
    if (line.subsystem?.includes(needle))
        return true;
    if (line.module?.includes(channel))
        return true;
    return false;
}
async function readTailLines(file, limit) {
    const stat = await fs.stat(file).catch(() => null);
    if (!stat)
        return [];
    const size = stat.size;
    const start = Math.max(0, size - MAX_BYTES);
    const handle = await fs.open(file, "r");
    try {
        const length = Math.max(0, size - start);
        if (length === 0)
            return [];
        const buffer = Buffer.alloc(length);
        const readResult = await handle.read(buffer, 0, length, start);
        const text = buffer.toString("utf8", 0, readResult.bytesRead);
        let lines = text.split("\n");
        if (start > 0)
            lines = lines.slice(1);
        if (lines.length && lines[lines.length - 1] === "") {
            lines = lines.slice(0, -1);
        }
        if (lines.length > limit) {
            lines = lines.slice(lines.length - limit);
        }
        return lines;
    }
    finally {
        await handle.close();
    }
}
export async function channelsLogsCommand(opts, runtime = defaultRuntime) {
    const channel = parseChannelFilter(opts.channel);
    const limitRaw = typeof opts.lines === "string" ? Number(opts.lines) : opts.lines;
    const limit = typeof limitRaw === "number" && Number.isFinite(limitRaw) && limitRaw > 0
        ? Math.floor(limitRaw)
        : DEFAULT_LIMIT;
    const file = getResolvedLoggerSettings().file;
    const rawLines = await readTailLines(file, limit * 4);
    const parsed = rawLines
        .map(parseLogLine)
        .filter((line) => Boolean(line));
    const filtered = parsed.filter((line) => matchesChannel(line, channel));
    const lines = filtered.slice(Math.max(0, filtered.length - limit));
    if (opts.json) {
        runtime.log(JSON.stringify({ file, channel, lines }, null, 2));
        return;
    }
    runtime.log(theme.info(`日志文件: ${file}`));
    if (channel !== "all") {
        runtime.log(theme.info(`通道: ${channel}`));
    }
    if (lines.length === 0) {
        runtime.log(theme.muted("没有匹配的日志行。"));
        return;
    }
    for (const line of lines) {
        const ts = line.time ? `${line.time} ` : "";
        const level = line.level ? `${line.level.toLowerCase()} ` : "";
        runtime.log(`${ts}${level}${line.message}`.trim());
    }
}
