/**
 * CLI 配置子命令
 * soloforge config resolve   — 解析配置字段优先级（只读）
 * soloforge config explain   — 解释字段来源和优先级（只读，中文）
 * soloforge config confirm   — 确认配置字段值（写入 config + evidence）
 * soloforge config unset     — 移除确认配置和 evidence
 */
import crypto from "node:crypto";
import fss from "node:fs";
import path from "node:path";
import YAML from "yaml";
import { createConfigEvidenceEntry, } from "../engine/config/config_precedence_contract/evidence.js";
import { explainField } from "../engine/config/config_precedence_contract/governance.js";
import { isCClassField, mapEvidenceSource, } from "../engine/config/config_precedence_contract/resolution.js";
import { repairProjectConfig } from "../engine/config/config_auto_repair.js";
import { debug, userInfo, userError } from "../engine/core/logger.js";
import { atomicWriteFileSync } from "../engine/core/write_file_atomic.js";
import { EXIT } from "../engine/core/exit_codes.js";
import { SoloForgeError } from "../engine/core/errors.js";
import { safeJsonParse } from "../engine/core/helpers.js";
// ── Evidence 持久化 ──
function normalizeEntry(e) {
    return { ...e, source: mapEvidenceSource(e.source) };
}
/**
 * 执行 loadConfigEvidenceEntries 操作
 */
export function loadConfigEvidenceEntries(projectPath) {
    debug("config_commands", "loadConfigEvidenceEntries() 开始执行");
    const evidencePath = path.join(projectPath, ".soloforge", "config.evidence.json");
    try {
        const raw = fss.readFileSync(evidencePath, "utf-8");
        // eslint-disable-next-line @typescript-eslint/no-explicit-any -- MCP SDK 桥接/动态 JSON 解析，字段由运行时决定
        const parsed = safeJsonParse(raw);
        if (Array.isArray(parsed))
            return parsed.map(normalizeEntry);
        if (parsed.entries && Array.isArray(parsed.entries))
            return parsed.entries.map(normalizeEntry);
        if (parsed.fields) {
            return Object.entries(parsed.fields).map(([k, v]) => {
                const field = v;
                return {
                    field_path: k,
                    value_hash: hashString(JSON.stringify(field.value)),
                    source: mapConfidenceSource(field.confidence_source),
                    confidence: field.confidence === "high" ? 1.0 : field.confidence === "medium" ? 0.6 : 0.3,
                    evidence_refs: field.evidence ?? [],
                    lifetime: "project_persistent",
                    collected_at: parsed.generated_at || new Date().toISOString(),
                };
            });
        }
        return [];
    }
    catch {
        debug("config_commands", "加载 config evidence 失败，返回空列表");
        return [];
    }
}
/**
 * 执行 writeConfigEvidenceEntries 操作
 */
export function writeConfigEvidenceEntries(projectPath, entries) {
    debug("config_commands", "writeConfigEvidenceEntries() 开始执行");
    const evidencePath = path.join(projectPath, ".soloforge", "config.evidence.json");
    const payload = {
        schema_version: 2,
        entries,
        updated_at: new Date().toISOString(),
    };
    atomicWriteFileSync(evidencePath, JSON.stringify(payload, null, 2), "utf-8");
}
// ── Config YAML 字段操作 ──
function updateConfigYamlField(projectPath, fieldPath, value) {
    debug("config_commands", "更新配置字段 —", fieldPath);
    const configPath = path.join(projectPath, ".soloforge", "config.yaml");
    let config = {};
    try {
        config = YAML.parse(fss.readFileSync(configPath, "utf-8")) || {};
    }
    catch {
        debug("config_commands", "解析配置文件失败，使用空配置");
    }
    const parts = fieldPath.split(".");
    let obj = config;
    for (let i = 0; i < parts.length - 1; i++) {
        if (!obj[parts[i]])
            obj[parts[i]] = {};
        obj = obj[parts[i]];
    }
    obj[parts[parts.length - 1]] = value;
    atomicWriteFileSync(configPath, YAML.stringify(config), "utf-8");
}
function removeConfigYamlField(projectPath, fieldPath) {
    debug("config_commands", "移除配置字段 —", fieldPath);
    const configPath = path.join(projectPath, ".soloforge", "config.yaml");
    let config = {};
    try {
        config = YAML.parse(fss.readFileSync(configPath, "utf-8")) || {};
    }
    catch {
        debug("config_commands", "解析配置文件失败，使用空配置");
    }
    const parts = fieldPath.split(".");
    let obj = config;
    for (let i = 0; i < parts.length - 1; i++) {
        if (!obj[parts[i]])
            return;
        obj = obj[parts[i]];
    }
    delete obj[parts[parts.length - 1]];
    atomicWriteFileSync(configPath, YAML.stringify(config), "utf-8");
}
// ── 辅助函数 ──
function hashString(str) {
    return crypto.createHash("sha256").update(str).digest("hex").slice(0, 16);
}
function mapConfidenceSource(source) {
    return mapEvidenceSource(source === "inferred" ? "knowledge_default" : source);
}
// ── 命令 ──
/**
 * 执行 cmdConfigResolve 操作
 */
export async function cmdConfigResolve() {
    debug("config_commands", "cmdConfigResolve() 开始执行");
    const projectPath = process.cwd();
    const argv = process.argv.slice(3);
    const fieldPath = argv[1] && !argv[1].startsWith("-") ? argv[1] : undefined;
    const opts = fieldPath ? { fields: [fieldPath] } : undefined;
    const { resolveCurrentProjectConfigReports } = await import("../engine/config/config_precedence_contract.js");
    const { resolutions, reports, warnings } = await resolveCurrentProjectConfigReports(projectPath, opts);
    userInfo("配置优先级解析结果:");
    userInfo("═".repeat(50));
    for (const r of resolutions) {
        userInfo("");
        userInfo(`字段: ${r.field_path}`);
        userInfo(`  采用值: ${JSON.stringify(r.resolved_value)}`);
        userInfo(`  来源: ${r.source}`);
        if (r.stale_warning)
            userInfo(`  ⚠️ stale: ${r.stale_warning}`);
        if (r.conflict_report)
            userInfo(`  冲突报告:\n${r.conflict_report}`);
    }
    for (const report of reports) {
        if (report.candidates.length > 1) {
            userInfo("");
            userInfo(`字段 ${report.field_path} 候选来源:`);
            for (const c of report.candidates) {
                userInfo(`  - ${c.source}: ${JSON.stringify(c.value)} (置信度: ${c.confidence})`);
            }
        }
    }
    if (warnings.length > 0) {
        userInfo("");
        userInfo("警告:");
        for (const w of warnings)
            userInfo(`  ⚠️ ${w}`);
    }
}
/**
 * 执行 cmdConfigExplain 操作
 */
export async function cmdConfigExplain() {
    debug("config_commands", "执行 cmdConfigExplain");
    const argv = process.argv.slice(3);
    const fieldPath = argv[1];
    if (!fieldPath) {
        userError("用法: soloforge config explain <field_path>");
        userError("示例: soloforge config explain product_profile");
        process.exit(EXIT.CONFIG);
    }
    const projectPath = process.cwd();
    const { resolveCurrentProjectConfigReports } = await import("../engine/config/config_precedence_contract.js");
    const { reports } = await resolveCurrentProjectConfigReports(projectPath, { fields: [fieldPath] });
    if (reports.length > 0) {
        userInfo(explainField(reports[0]));
    }
    else {
        userInfo(`字段 ${fieldPath} 无候选来源`);
    }
}
/**
 * 执行 cmdConfigConfirm 操作
 */
export async function cmdConfigConfirm() {
    debug("config_commands", "执行 cmdConfigConfirm");
    const argv = process.argv.slice(3);
    const fieldPath = argv[1];
    const rawValue = argv[2];
    if (!fieldPath || rawValue === undefined) {
        userError("用法: soloforge config confirm <field_path> <value>");
        userError("示例: soloforge config confirm product_profile saas");
        process.exit(EXIT.CONFIG);
    }
    const projectPath = process.cwd();
    if (isCClassField(fieldPath)) {
        userInfo(`⚠️  C 类字段 ${fieldPath} 需要显式确认。此操作将写入 config.yaml 和 evidence。`);
    }
    let value = rawValue;
    const parsedValue = safeJsonParse(rawValue);
    if (parsedValue !== undefined)
        value = parsedValue;
    updateConfigYamlField(projectPath, fieldPath, value);
    const entries = loadConfigEvidenceEntries(projectPath);
    const existingIdx = entries.findIndex(e => e.field_path === fieldPath);
    const newEntry = createConfigEvidenceEntry(fieldPath, value, "confirmed_config", {
        confidence: 1.0,
        evidence_refs: ["config confirm"],
        confirmed_by: process.env.USER || "cli",
    });
    if (existingIdx >= 0) {
        entries[existingIdx] = newEntry;
    }
    else {
        entries.push(newEntry);
    }
    writeConfigEvidenceEntries(projectPath, entries);
    userInfo(`✅ 已确认 ${fieldPath} = ${JSON.stringify(value)}`);
    userInfo("   config.yaml 和 config.evidence.json 已更新");
}
/**
 * 执行 cmdConfigUnset 操作
 */
export async function cmdConfigUnset() {
    debug("config_commands", "执行 cmdConfigUnset");
    const argv = process.argv.slice(3);
    const fieldPath = argv[1];
    if (!fieldPath) {
        userError("用法: soloforge config unset <field_path>");
        process.exit(EXIT.CONFIG);
    }
    const projectPath = process.cwd();
    removeConfigYamlField(projectPath, fieldPath);
    const entries = loadConfigEvidenceEntries(projectPath);
    const filtered = entries.filter(e => e.field_path !== fieldPath);
    writeConfigEvidenceEntries(projectPath, filtered);
    userInfo(`✅ 已移除 ${fieldPath} 的确认配置和 evidence`);
}
/**
 * 执行 cmdConfigRepair 操作
 */
export async function cmdConfigRepair() {
    debug("config_commands", "执行 cmdConfigRepair");
    const argv = process.argv.slice(3);
    const dryRun = argv.includes("--dry-run");
    const isJson = argv.includes("--json");
    const projectPath = process.cwd();
    const result = repairProjectConfig(projectPath, { dry_run: dryRun });
    if (isJson) {
        userInfo(JSON.stringify({
            changed: result.changed,
            dry_run: result.dry_run,
            needs_repair: result.needs_repair,
            auto_resolvable: result.auto_resolvable,
            issue_count: result.issues.length,
            issues: result.issues,
            backup_paths: result.backup_paths,
            parse_error: result.parse_error,
        }, null, 2));
        return;
    }
    userInfo("配置自动修复:");
    if (!result.config_exists) {
        userInfo("  未发现 .soloforge/config.yaml，无需修复。");
        userInfo("  新项目请先运行 soloforge init 或 soloforge init --auto。");
        return;
    }
    if (result.parse_error) {
        throw new SoloForgeError(`config.yaml 无法解析: ${result.parse_error}`, "CONFIG_PARSE_ERROR", "error", "手动修正 YAML 语法后重试");
    }
    if (result.issues.length === 0) {
        userInfo("  ✅ 未发现需要自动修复的配置问题。");
        return;
    }
    for (const issue of result.issues) {
        userInfo(`  - [${issue.kind}] ${issue.field_path}: ${issue.message_zh}`);
        if (issue.before !== undefined || issue.after !== undefined) {
            userInfo(`    ${JSON.stringify(issue.before)} -> ${JSON.stringify(issue.after)}`);
        }
    }
    if (dryRun) {
        userInfo("  dry-run: 未写入文件。去掉 --dry-run 后会自动备份并修复。");
        return;
    }
    if (result.changed) {
        userInfo("  ✅ config.yaml 与 config.evidence.json 已修复并重签。");
        if (result.backup_paths.length > 0) {
            userInfo("  备份:");
            for (const p of result.backup_paths)
                userInfo(`    - ${p}`);
        }
        userInfo("  下一步: soloforge validate && soloforge status && soloforge next");
    }
}
//# sourceMappingURL=config_commands.js.map