/**
 * Sink loader — reads config/sinks.yaml, resolves env vars, validates,
 * and instantiates sink objects.
 *
 * Fire-and-forget: parse failures log a warning and return an empty array
 * so the pipeline never crashes due to sink misconfiguration.
 *
 * @see docs/design-docs/report-store/sink-architecture.md
 */
import { dirname, resolve } from "path";
import { fileURLToPath } from "url";
import { interpolate } from "../interpolate.js";
import { tryLoadConfigFile } from "../pipeline/compiler/config-loader.js";
import { BigQuerySink } from "./bigquery/index.js";
import { SinksFileSchema } from "./schema.js";
import { resolveDashboardBaseUrl } from "./slack/dashboard-links.js";
import { SlackSink } from "./slack/index.js";
import { WebhookSink } from "./webhook/index.js";
// ---------------------------------------------------------------------------
// Paths
// ---------------------------------------------------------------------------
const __dirname = dirname(fileURLToPath(import.meta.url));
const PACKAGE_ROOT = resolve(__dirname, "..", "..");
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Load and instantiate all enabled sinks from `config/sinks.yaml`.
 *
 * Returns an empty array when:
 * - The config file doesn't exist (no sinks configured)
 * - The config file fails to parse or validate
 */
export function loadSinks() {
    const loaded = tryLoadConfigFile("sinks", PACKAGE_ROOT);
    if (!loaded) {
        return [];
    }
    try {
        const interpolated = interpolate(loaded.data);
        // When all sinks are commented out, js-yaml returns { sinks: null }.
        // Normalize null → undefined so Zod's .default([]) can apply.
        const normalized = interpolated && typeof interpolated === "object"
            ? Object.fromEntries(Object.entries(interpolated).map(([k, v]) => [k, v === null ? undefined : v]))
            : interpolated;
        const validated = SinksFileSchema.parse(normalized);
        return validated.sinks
            .filter((s) => s.enabled)
            .map((s) => createSink(s))
            .filter((sink) => sink !== null);
    }
    catch (error) {
        console.warn("Failed to load sinks config — continuing without sinks:", error instanceof Error ? error.message : error);
        return [];
    }
}
// ---------------------------------------------------------------------------
// Factory
// ---------------------------------------------------------------------------
function createSink(config) {
    switch (config.type) {
        case "bigquery":
            return new BigQuerySink({
                credentials: config.credentials,
                dataset: config.dataset,
                project: config.project,
            });
        case "github-comment":
            console.log("  ℹ️  GitHubCommentSink not yet implemented — skipping");
            return null;
        case "slack":
            return new SlackSink(config.webhookUrl, resolveDashboardBaseUrl(), config.channel);
        case "webhook":
            return new WebhookSink(config.url, config.headers ?? {});
        default: {
            const _exhaustive = config;
            console.warn(`  ⚠️  Unknown sink type: ${_exhaustive.type}`);
            return null;
        }
    }
}
