"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderToolsetManual = renderToolsetManual;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const registry_1 = require("../registry");
const spec_1 = require("./spec");
const MAX_REGISTERED_TOOL_NAMES_IN_MANUAL = 200;
function renderToolsetManual(input) {
    const meta = (0, registry_1.getToolsetMeta)(input.toolsetId);
    if (!meta) {
        return { foundToolset: false, content: '' };
    }
    const spec = resolveManualSpec(meta.manualSpec, meta.promptFilesI18n);
    const resolvedTopics = resolveRequestedTopics(input.request, spec);
    const topicSections = [];
    const missingTopics = [];
    for (const topic of resolvedTopics) {
        const generatedBody = renderGeneratedTopicBody({
            toolsetId: input.toolsetId,
            topic,
            language: input.language,
            spec,
        });
        if (generatedBody !== null) {
            topicSections.push({
                topic,
                title: (0, spec_1.getManualTopicTitle)(topic, input.language, spec),
                body: generatedBody,
            });
            continue;
        }
        const loaded = loadTopicDoc({
            toolsetId: input.toolsetId,
            topic,
            language: input.language,
            spec,
        });
        if (loaded.status !== 'ok') {
            if ((0, spec_1.shouldWarnMissingSection)(spec)) {
                missingTopics.push({ topic, filePath: loaded.filePath, status: loaded.status });
            }
            continue;
        }
        const body = sanitizeManualBody(loaded.content);
        if (body === '') {
            if ((0, spec_1.shouldWarnMissingSection)(spec)) {
                missingTopics.push({ topic, filePath: loaded.filePath, status: 'missing' });
            }
            continue;
        }
        topicSections.push({
            topic,
            title: (0, spec_1.getManualTopicTitle)(topic, input.language, spec),
            body,
        });
    }
    const sections = [];
    const notice = meta.manualNoticeI18n?.[input.language]?.trim();
    if (notice) {
        sections.push(notice);
    }
    if (missingTopics.length > 0) {
        sections.push(renderMissingTopicsWarning(input.language, input.toolsetId, missingTopics));
    }
    for (const section of topicSections) {
        sections.push(`### ${section.title}\n\n${section.body}`);
    }
    if (sections.length === 0) {
        const fallback = input.language === 'zh'
            ? `该工具集 '${input.toolsetId}' 暂未配置手册。`
            : `Toolset '${input.toolsetId}' has no manual configured.`;
        return { foundToolset: true, content: fallback };
    }
    const title = input.language === 'zh'
        ? `**工具集手册：${input.toolsetId}**`
        : `**Toolset manual: ${input.toolsetId}**`;
    return { foundToolset: true, content: `${title}\n\n${sections.join('\n\n---\n\n')}` };
}
function renderGeneratedTopicBody(params) {
    if (params.topic !== 'tools') {
        return null;
    }
    const spec = params.spec;
    if (!spec || spec.toolsTopicMode !== 'registered-tool-name-list') {
        return null;
    }
    return renderRegisteredToolNameList(params.language, params.toolsetId);
}
function renderRegisteredToolNameList(language, toolsetId) {
    const toolset = (0, registry_1.getToolset)(toolsetId);
    const toolNames = toolset ? toolset.map((tool) => tool.name) : [];
    if (toolNames.length === 0) {
        return language === 'zh'
            ? '当前该工具集没有注册可调用工具。'
            : 'This toolset currently has no registered callable tools.';
    }
    const shownToolNames = toolNames.slice(0, MAX_REGISTERED_TOOL_NAMES_IN_MANUAL);
    const omittedToolCount = toolNames.length - shownToolNames.length;
    const listParts = shownToolNames.map((name) => `- \`${name}\``);
    if (omittedToolCount > 0) {
        listParts.push(language === 'zh'
            ? `- ...（另有 ${omittedToolCount} 个工具未展示）`
            : `- ... (${omittedToolCount} more tool(s) omitted)`);
    }
    const list = listParts.join('\n');
    if (language === 'zh') {
        return [
            '该工具集来自标准 MCP 协议接入，工具契约详见系统提示中的各工具函数说明。',
            '',
            `当前注册在该工具集下的工具（共 ${toolNames.length} 个）：`,
            '',
            list,
        ].join('\n');
    }
    return [
        'This toolset is a standard Raw MCP protocol integration. See the individual function-tool descriptions in the system prompt for the tool contract.',
        '',
        `Tools currently registered under this toolset (${toolNames.length} total):`,
        '',
        list,
    ].join('\n');
}
function resolveRequestedTopics(request, spec) {
    const allowedTopics = new Set((0, spec_1.getManualSpecTopics)(spec));
    const topicArg = request.requestedTopic;
    if (topicArg && typeof topicArg === 'string') {
        if (topicArg === 'all') {
            return [...allowedTopics];
        }
        if (isManualTopic(topicArg) && allowedTopics.has(topicArg)) {
            return [topicArg];
        }
    }
    const topicsArg = request.requestedTopics;
    if (Array.isArray(topicsArg) && topicsArg.length > 0) {
        const deduped = [];
        const seen = new Set();
        for (const entry of topicsArg) {
            if (!isManualTopic(entry))
                continue;
            if (!allowedTopics.has(entry))
                continue;
            if (seen.has(entry))
                continue;
            seen.add(entry);
            deduped.push(entry);
        }
        if (deduped.length > 0) {
            return deduped;
        }
    }
    const defaults = spec_1.DEFAULT_MANUAL_TOPICS.filter((topic) => allowedTopics.has(topic));
    if (defaults.length > 0) {
        return [...defaults];
    }
    return [...allowedTopics];
}
function loadTopicDoc(params) {
    const topicPath = resolveTopicPath(params.toolsetId, params.topic, params.language, params.spec);
    if (!topicPath) {
        return { status: 'missing', filePath: '', content: '' };
    }
    // rtws-relative paths (start with '.') are resolved from rtws root (cwd);
    // package-relative paths (used by builtin toolsets) are resolved from __dirname.
    const absPath = topicPath.startsWith('.')
        ? path.resolve(process.cwd(), topicPath)
        : path.resolve(__dirname, '..', topicPath);
    try {
        const content = fs.readFileSync(absPath, 'utf8');
        return { status: 'ok', filePath: topicPath, content };
    }
    catch (error) {
        if (isNodeErrno(error, 'ENOENT')) {
            return { status: 'missing', filePath: topicPath, content: '' };
        }
        return { status: 'error', filePath: topicPath, content: '' };
    }
}
function resolveTopicPath(toolsetId, topic, language, spec) {
    const fromSpec = spec?.topicFilesI18n?.[language]?.[topic];
    if (typeof fromSpec === 'string' && fromSpec.trim() !== '') {
        return fromSpec;
    }
    const meta = (0, registry_1.getToolsetMeta)(toolsetId);
    const basePath = meta?.promptFilesI18n?.[language];
    if (!basePath) {
        return null;
    }
    const baseDir = path.dirname(basePath);
    return path.join(baseDir, `${topic}.md`);
}
function resolveManualSpec(spec, promptFilesI18n) {
    if (spec) {
        return spec;
    }
    const enBase = promptFilesI18n?.en;
    const zhBase = promptFilesI18n?.zh;
    if (!enBase && !zhBase) {
        return undefined;
    }
    const out = {
        topics: spec_1.MANUAL_TOPICS,
        warnOnMissing: true,
        topicFilesI18n: {
            en: enBase ? topicPathsFromBase(enBase) : undefined,
            zh: zhBase ? topicPathsFromBase(zhBase) : undefined,
        },
    };
    return out;
}
function topicPathsFromBase(baseIndexPath) {
    const baseDir = path.dirname(baseIndexPath);
    return {
        index: path.join(baseDir, 'index.md'),
        principles: path.join(baseDir, 'principles.md'),
        tools: path.join(baseDir, 'tools.md'),
        scenarios: path.join(baseDir, 'scenarios.md'),
        errors: path.join(baseDir, 'errors.md'),
    };
}
function renderMissingTopicsWarning(language, toolsetId, missingTopics) {
    const header = language === 'zh'
        ? `> ⚠️ 手册章节缺失（toolset: \`${toolsetId}\`）`
        : `> ⚠️ Missing manual sections (toolset: \`${toolsetId}\`)`;
    const details = missingTopics
        .map((item) => {
        const label = language === 'zh'
            ? item.status === 'error'
                ? '读取失败'
                : '缺失'
            : item.status === 'error'
                ? 'read error'
                : 'missing';
        const pathInfo = item.filePath !== '' ? ` (${item.filePath})` : '';
        return `> - \`${item.topic}\`: ${label}${pathInfo}`;
    })
        .join('\n');
    return [header, details].join('\n');
}
function isManualTopic(value) {
    return spec_1.MANUAL_TOPICS.includes(value);
}
function isNodeErrno(error, code) {
    if (!error || typeof error !== 'object')
        return false;
    const maybeCode = error.code;
    return typeof maybeCode === 'string' && maybeCode === code;
}
function sanitizeManualBody(content) {
    const lines = content.split('\n');
    const out = [];
    let inCodeBlock = false;
    let skippingTemplate = false;
    let templateHeadingLevel = 0;
    for (const rawLine of lines) {
        const line = rawLine.endsWith('\r') ? rawLine.slice(0, -1) : rawLine;
        const trimmedStart = line.trimStart();
        const isFence = isFenceLine(trimmedStart);
        if (isFence) {
            inCodeBlock = !inCodeBlock;
            if (!skippingTemplate) {
                out.push(line);
            }
            continue;
        }
        const heading = inCodeBlock ? null : parseHeading(trimmedStart);
        if (skippingTemplate) {
            if (!inCodeBlock && heading && heading.level <= templateHeadingLevel) {
                skippingTemplate = false;
            }
            else {
                continue;
            }
        }
        if (!inCodeBlock && heading) {
            if (heading.level === 1) {
                continue;
            }
            if (isTemplateHeadingText(heading.text)) {
                skippingTemplate = true;
                templateHeadingLevel = heading.level;
                continue;
            }
            const normalizedLevel = normalizeHeadingLevel(heading.level);
            if (normalizedLevel !== heading.level) {
                const leading = line.slice(0, line.length - trimmedStart.length);
                out.push(`${leading}${'#'.repeat(normalizedLevel)} ${heading.text}`);
                continue;
            }
        }
        out.push(line);
    }
    return out.join('\n').trim();
}
function isFenceLine(trimmedStart) {
    return trimmedStart.startsWith('```') || trimmedStart.startsWith('~~~');
}
function parseHeading(trimmedStart) {
    if (!trimmedStart.startsWith('#')) {
        return null;
    }
    const match = /^(#{1,6})\s+(.+)$/.exec(trimmedStart);
    if (!match) {
        return null;
    }
    return { level: match[1].length, text: match[2] ?? '' };
}
function normalizeHeadingLevel(level) {
    if (level <= 3) {
        return 4;
    }
    return level;
}
function isTemplateHeadingText(text) {
    const title = text.trimStart();
    if (title.toLowerCase().startsWith('template')) {
        return true;
    }
    return title.startsWith('模板');
}
