import path from "node:path";
import { fileExists, readYamlDocument } from "../review/review-artifact-utils.js";
import { adoptProfile, mergeOrthogonalFields, } from "./config-profile.js";
async function readConfigAt(dir) {
    const configPath = path.join(dir, ".onto", "config.yml");
    if (!(await fileExists(configPath))) {
        return {};
    }
    const raw = await readYamlDocument(configPath);
    if (raw === null || typeof raw !== "object") {
        return {};
    }
    assertKnownConfigKeys(raw, configPath);
    return raw;
}
const TOP_LEVEL_CONFIG_KEYS = [
    "llm",
    "review",
    "review_mode",
    "max_concurrent_lenses",
    "domain",
    "secondary_domains",
    "domains",
    "excluded_names",
    "max_listing_depth",
    "max_listing_entries",
    "max_embed_lines",
    "output_language",
    "learning_extract_mode",
    "main_llm",
    "lens_agent_teams_mode",
];
function assertKnownConfigKeys(raw, configPath) {
    const allowed = new Set(TOP_LEVEL_CONFIG_KEYS);
    const unknown = Object.keys(raw).filter((key) => !allowed.has(key));
    if (unknown.length === 0)
        return;
    throw new Error([
        `Unsupported .onto config key(s) in ${configPath}: ${unknown.join(", ")}`,
        "Supported top-level keys:",
        `  ${TOP_LEVEL_CONFIG_KEYS.join(", ")}`,
        "LLM selection belongs under:",
        "  llm:",
        "    auth: oauth | api_key | local",
        "    provider: openai | anthropic | grok | lmstudio",
        "    model: <model-id>",
        "    effort: high",
        "    base_url: <optional>",
    ].join("\n"));
}
/**
 * Orthogonal-only config chain resolver.
 *
 * # What this is
 *
 * Reads home + project `.onto/config.yml`, merges ONLY the orthogonal
 * fields (output_language, domains, review_mode, learning_extract_mode,
 * etc. — see `config-profile.ts:PROFILE_FIELDS` for the complement set),
 * and returns the merged partial config without running `adoptProfile`.
 *
 * # Why this exists
 *
 * Callers that only need a single orthogonal field (e.g.,
 * `resolveReviewSessionExtractMode` reading `learning_extract_mode`) do
 * NOT need provider-profile validation. Routing them through
 * `resolveConfigChain` caused false fail-fast throws once PR #96's atomic
 * profile adoption started rejecting "no provider profile declared"
 * configs — a test/tooling fixture that cares only about orthogonal
 * settings would be blocked by an unrelated profile gate.
 *
 * # How it relates
 *
 * Same underlying `readConfigAt` + `mergeOrthogonalFields` that
 * `resolveConfigChain` uses, sequenced without profile adoption.
 * Callers that need a full config continue to use `resolveConfigChain`.
 */
export async function resolveOrthogonalConfigChain(ontoHome, projectRoot) {
    const homeConfig = await readConfigAt(ontoHome);
    const sameRoot = ontoHome === projectRoot;
    const projectConfig = sameRoot ? homeConfig : await readConfigAt(projectRoot);
    return mergeOrthogonalFields(homeConfig, projectConfig);
}
/**
 * Config chain resolver (home + project) with atomic profile adoption.
 *
 * # Behavior
 *
 *   - Project declares any profile fields  → project owns the profile atomically.
 *   - Project declares none, home declares some → global profile adopted silently.
 *   - Neither side declares any profile fields → empty profile returned.
 *
 * Orthogonal fields (output_language, domains, review_mode, listing limits,
 * learning_extract_mode, etc.) continue to merge last-wins — they do not
 * carry cross-provider semantics.
 *
 * # Why atomic adoption still runs
 *
 * Atomic ownership prevents mixed provider state from different config files.
 * `extractProfileFields` + `adoptProfile` transfer PROFILE_FIELDS as a group
 * from exactly one source.
 */
export async function resolveConfigChain(ontoHome, projectRoot) {
    const homeConfig = await readConfigAt(ontoHome);
    const sameRoot = ontoHome === projectRoot;
    const projectConfig = sameRoot ? homeConfig : await readConfigAt(projectRoot);
    const homePath = path.join(ontoHome, ".onto", "config.yml");
    const projectPath = path.join(projectRoot, ".onto", "config.yml");
    const adoption = adoptProfile({
        home: homeConfig,
        project: projectConfig,
        homePath,
        projectPath,
        sameRoot,
    });
    const orthogonal = mergeOrthogonalFields(homeConfig, projectConfig);
    const merged = { ...orthogonal, ...adoption.profile };
    return merged;
}
