/**
 * Pipeline step: Mirror repo-based tasks to the Content Lake.
 *
 * When --repo-tasks-path is provided, this step upserts mirror documents
 * in the Sanity Content Lake for all repo-sourced tasks. This makes
 * repo tasks visible in Studio with full provenance tracking.
 *
 * The step is optional — mirror failure does not block the pipeline.
 * It runs after validate and before fetch-docs so mirror documents
 * exist before evaluation begins.
 *
 * @see packages/eval/src/pipeline/mirror-repo-tasks.ts
 * @see docs/archive/exec-plans/tasks-as-content/phase-5-content-lake-mirroring.md
 */
import { getAilfSanityClient, getSanityClient } from "../../sanity/client.js";
import { detectGitContext, mirrorRepoTasks, } from "../../pipeline/mirror-repo-tasks.js";
export class MirrorRepoTasksStep {
    name = "mirror-repo-tasks";
    optional = true;
    check(_ctx) {
        // This step is optional — no hard preconditions
        // If no repo-tasks-path, it will be skipped in execute()
        return [];
    }
    async execute(ctx) {
        const start = Date.now();
        // Skip if no repo tasks configured
        if (!ctx.config.repoTasksPath) {
            return { status: "skipped", reason: "No --repo-tasks-path provided" };
        }
        // W0145 — never mirror under repo-only mode. The API gateway maps
        // PipelineRequest.taskMode="inline" → taskSourceType="repo", so an
        // external consumer's ephemeral inline tasks would otherwise be
        // upserted into AILF's canonical Content Lake. Mirroring is only
        // correct for the in-tree dogfood path (taskSourceType unset +
        // repoTasksPath set, e.g. external-eval.yml).
        if (ctx.config.taskSourceType === "repo") {
            return {
                status: "skipped",
                reason: 'taskSourceType="repo" — inline tasks are not mirrored',
            };
        }
        // Need a write token for mirroring
        const token = process.env.AILF_REPORT_SANITY_API_TOKEN ?? process.env.SANITY_API_TOKEN;
        if (!token) {
            return {
                status: "skipped",
                reason: "No write token available for Content Lake mirroring",
            };
        }
        try {
            // Load repo tasks via the task source
            // The CompositeTaskSource is already wired — but we only want
            // the repo tasks, not the Content Lake ones. Load directly from
            // RepoTaskSource via a fresh instance.
            const { RepoTaskSource } = await import("../../adapters/task-sources/repo-task-source.js");
            const repoSource = new RepoTaskSource(ctx.config.repoTasksPath);
            const repoTasks = (await repoSource.loadTasks()).filter((t) => t.mode === "literacy");
            if (repoTasks.length === 0) {
                return {
                    durationMs: Date.now() - start,
                    status: "success",
                    summary: "No repo tasks to mirror",
                };
            }
            // Detect git context (from env vars or git CLI)
            const git = await detectGitContext(ctx.config.repoTasksPath);
            ctx.logger.info(`  Mirroring ${repoTasks.length} repo task(s) from ${git.repo}@${git.branch}`);
            // Two clients are required after the D0043 dataset split:
            //   - `client` writes ailf.task / ailf.featureArea to the AILF
            //     dataset and reads existing mirror state — uses the
            //     AILF-scoped token explicitly so writes work even when
            //     SANITY_API_TOKEN is editorial-read-only.
            //   - `editorialClient` resolves `article` slugs against the
            //     editorial dataset. Operators may scope the AILF token to
            //     AILF only (D0043 consequence #5); using it here would
            //     401 on the editorial query. Let it pick up SANITY_API_TOKEN
            //     from the default config instead.
            const client = getAilfSanityClient({ token });
            const editorialClient = getSanityClient();
            // Run the mirror
            const result = await mirrorRepoTasks({
                client,
                editorialClient,
                git,
                logger: ctx.logger,
                tasks: repoTasks,
            });
            // Log results
            if (result.areasCreated.length > 0) {
                ctx.logger.info(`  Auto-created feature areas: ${result.areasCreated.join(", ")}`);
            }
            if (result.unresolvedSlugs.length > 0) {
                ctx.logger.warn(`  Unresolved canonical doc slugs: ${result.unresolvedSlugs.join(", ")}`);
            }
            for (const err of result.errors) {
                ctx.logger.warn(`  Mirror error: ${err}`);
            }
            return {
                durationMs: Date.now() - start,
                status: "success",
                summary: `Mirrored ${result.upserted} task(s), skipped ${result.skipped} unchanged` +
                    (result.errors.length > 0
                        ? ` (${result.errors.length} error(s))`
                        : ""),
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            ctx.logger.warn(`Mirror step failed (non-blocking): ${msg}`);
            return {
                durationMs: Date.now() - start,
                status: "success",
                summary: `Mirror failed (non-blocking): ${msg}`,
            };
        }
    }
}
