/**
 * commands/init-config-injection.ts — pure helpers for `ailf init`.
 *
 * Injects user-supplied owner/source values into the scaffolded config
 * templates by replacing a *commented* owner block (anchored) and the
 * named-source line. With no values supplied, every injector returns
 * its input unchanged — so `ailf init` output stays byte-identical to the
 * shipped template. Anchor drift is caught by init-config-injection.test.ts.
 *
 * Source handling: the template references the registered `production`
 * source by name. Supplied source values that all match the production
 * defaults keep the named reference (so the happy path never lands in the
 * `env-override` → `experimental` bucket, D0059); any diverging value
 * swaps the named line for an inline source block, with production
 * defaults filling the unsupplied fields.
 */
// ---------------------------------------------------------------------------
// Anchors — kept in sync with packages/core/examples/{ailf.config.ts,
// ailf-config.yaml, ailf-eval-workflow.yml}. The drift-guard tests fail loudly
// if these stop matching.
// ---------------------------------------------------------------------------
export const TS_OWNER_ANCHOR = `  // owner: {
  //   team: "docs",
  //   individual: "you@sanity.io",
  // },`;
export const YAML_OWNER_ANCHOR = `# owner:
#   team: docs
#   individual: you@sanity.io`;
/** Placeholder team slug in the scaffolded GitHub Actions workflow env. */
export const WORKFLOW_OWNER_TEAM_ANCHOR = 'AILF_OWNER_TEAM: "<REPLACE-WITH-YOUR-TEAM-SLUG>"';
/** Named-source line in the TS template, replaced when values diverge. */
export const TS_SOURCE_ANCHOR = '  source: "production",';
/** Named-source line in the YAML template, replaced when values diverge. */
export const YAML_SOURCE_ANCHOR = "source: production";
/**
 * The values the registered `production` source resolves to. Supplied
 * source values matching these keep the template's named reference.
 */
const PRODUCTION_SOURCE_VALUES = {
    projectId: "3do82whm",
    dataset: "next",
    baseUrl: "https://www.sanity.io/docs",
};
// ---------------------------------------------------------------------------
// Validation
// ---------------------------------------------------------------------------
const SANITY_EMAIL = /^[^\s@]+@sanity\.io$/i;
/**
 * Validate an owner individual. Empty/undefined is allowed (means "omit").
 * Returns `true` when valid (matching @inquirer/prompts' validate contract),
 * or an error-message string otherwise.
 */
export function validateIndividual(value) {
    const trimmed = value?.trim() ?? "";
    if (trimmed === "")
        return true;
    if (!SANITY_EMAIL.test(trimmed)) {
        return `Individual must be an @sanity.io email address (got "${value}")`;
    }
    return true;
}
/** Prompts fire only when the session is interactive and --yes is unset. */
export function shouldPrompt(opts, isTty) {
    return isTty && !opts.yes;
}
// ---------------------------------------------------------------------------
// Injectors
// ---------------------------------------------------------------------------
function renderTsOwnerBlock(v) {
    const lines = [];
    if (v.team)
        lines.push(`    team: ${JSON.stringify(v.team)},`);
    if (v.individual)
        lines.push(`    individual: ${JSON.stringify(v.individual)},`);
    if (lines.length === 0)
        return "";
    return ["  owner: {", ...lines, "  },"].join("\n");
}
function renderYamlOwnerBlock(v) {
    const lines = [];
    if (v.team)
        lines.push(`  team: ${v.team}`);
    if (v.individual)
        lines.push(`  individual: ${v.individual}`);
    if (lines.length === 0)
        return "";
    return ["owner:", ...lines].join("\n");
}
/**
 * Resolve supplied source values into the inline block to write, or
 * `undefined` to keep the template's named `production` reference.
 *
 * Returns `undefined` when no source value was supplied, or when every
 * supplied value equals the production defaults — spelling the production
 * source inline would record `source.name = "env-override"` in provenance
 * and classify the run `experimental` (D0059), so the named reference is
 * kept whenever it is value-equivalent. A diverging value produces the
 * full inline tuple, with production defaults filling unsupplied fields
 * (matching the prior template behavior of overriding scalars in place).
 */
export function resolveSourceInjection(v) {
    if (!v.projectId && !v.dataset && !v.baseUrl)
        return undefined;
    const resolved = {
        projectId: v.projectId ?? PRODUCTION_SOURCE_VALUES.projectId,
        dataset: v.dataset ?? PRODUCTION_SOURCE_VALUES.dataset,
        baseUrl: v.baseUrl ?? PRODUCTION_SOURCE_VALUES.baseUrl,
    };
    const matchesProduction = resolved.projectId === PRODUCTION_SOURCE_VALUES.projectId &&
        resolved.dataset === PRODUCTION_SOURCE_VALUES.dataset &&
        resolved.baseUrl === PRODUCTION_SOURCE_VALUES.baseUrl;
    return matchesProduction ? undefined : resolved;
}
function renderTsSourceBlock(s) {
    return [
        "  source: {",
        `    projectId: ${JSON.stringify(s.projectId)},`,
        `    dataset: ${JSON.stringify(s.dataset)},`,
        `    baseUrl: ${JSON.stringify(s.baseUrl)},`,
        "  },",
    ].join("\n");
}
function renderYamlSourceBlock(s) {
    return [
        "source:",
        `  projectId: ${JSON.stringify(s.projectId)}`,
        `  dataset: ${s.dataset}`,
        `  baseUrl: ${JSON.stringify(s.baseUrl)}`,
    ].join("\n");
}
/** Inject values into the raw TypeScript config template. */
export function injectIntoTs(template, v) {
    let out = template;
    const ownerBlock = renderTsOwnerBlock(v);
    if (ownerBlock)
        out = out.replace(TS_OWNER_ANCHOR, ownerBlock);
    const inlineSource = resolveSourceInjection(v);
    if (inlineSource) {
        out = out.replace(TS_SOURCE_ANCHOR, renderTsSourceBlock(inlineSource));
    }
    return out;
}
/** Inject values into the raw YAML config template. */
export function injectIntoYaml(template, v) {
    let out = template;
    const ownerBlock = renderYamlOwnerBlock(v);
    if (ownerBlock)
        out = out.replace(YAML_OWNER_ANCHOR, ownerBlock);
    const inlineSource = resolveSourceInjection(v);
    if (inlineSource) {
        out = out.replace(YAML_SOURCE_ANCHOR, renderYamlSourceBlock(inlineSource));
    }
    return out;
}
/**
 * Inject the resolved owner team into the scaffolded GitHub Actions workflow,
 * replacing the placeholder slug. Only `team` is injected — the workflow's
 * `AILF_OWNER_INDIVIDUAL` stays `${{ github.actor }}` so CI attributes each run
 * to the user who triggered it. Without a resolved team the template is
 * returned unchanged (placeholder preserved for the user to edit by hand).
 *
 * This matters for correctness, not just convenience: the `AILF_OWNER_TEAM` env
 * var takes precedence over the config's `owner.team` (D0037), so an unedited
 * placeholder would otherwise override a team the user set in their config.
 */
export function injectIntoWorkflow(template, v) {
    if (!v.team)
        return template;
    return template.replace(WORKFLOW_OWNER_TEAM_ANCHOR, `AILF_OWNER_TEAM: ${JSON.stringify(v.team)}`);
}
/** Merge values into a parsed config object (the JSON output path). */
export function injectIntoData(data, v) {
    const out = { ...data };
    if (v.team || v.individual) {
        out.owner = {
            ...data.owner,
            ...(v.team ? { team: v.team } : {}),
            ...(v.individual ? { individual: v.individual } : {}),
        };
    }
    if (typeof data.source === "object") {
        // Pre-existing inline base: merge only the supplied values over it,
        // preserving its other fields (the pre-named-source behavior).
        if (v.projectId || v.dataset || v.baseUrl) {
            out.source = {
                ...data.source,
                ...(v.projectId ? { projectId: v.projectId } : {}),
                ...(v.dataset ? { dataset: v.dataset } : {}),
                ...(v.baseUrl ? { baseUrl: v.baseUrl } : {}),
            };
        }
    }
    else {
        // Named-source base: production-equivalent (or absent) values keep the
        // named reference; a diverging value swaps it for the inline block.
        const inlineSource = resolveSourceInjection(v);
        if (inlineSource)
            out.source = inlineSource;
    }
    return out;
}
