"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.collectCustomWorkerDoctorChecks = collectCustomWorkerDoctorChecks;
const node_fs_1 = require("node:fs");
const promises_1 = require("node:fs/promises");
const node_path_1 = __importDefault(require("node:path"));
const env_template_1 = require("../../config/env-template");
const catalog_1 = require("../../i18n/catalog");
const pi_worker_runtime_1 = require("../../worker/pi-worker-runtime");
const check_names_1 = require("./check-names");
async function collectCustomWorkerDoctorChecks(input) {
    const locale = input.locale ?? catalog_1.DEFAULT_APP_LOCALE;
    const env = input.env ?? process.env;
    const checks = [];
    for (const [worker, config] of Object.entries(input.config.customWorkers)) {
        checks.push(checkCustomWorkerConfig(worker, config, env, locale));
    }
    if (Object.keys(input.config.customWorkers).length > 0) {
        checks.push(await checkPiWorkerRuntime(locale, input.runtimeAvailabilityCheck ?? pi_worker_runtime_1.ensurePiWorkerRuntimeAvailable));
        checks.push(checkPiMcpAdapterPackage(locale));
        checks.push(await checkPiMcpConfigFiles(input.cwd, locale));
    }
    return checks;
}
function checkCustomWorkerConfig(worker, config, env, locale) {
    const name = (0, check_names_1.getDoctorProviderCheckName)(worker, locale);
    try {
        const baseUrl = resolveCustomWorkerValue(worker, "baseUrl", config.baseUrl, env);
        const parsedBaseUrl = new URL(baseUrl);
        if (parsedBaseUrl.protocol !== "http:" &&
            parsedBaseUrl.protocol !== "https:") {
            throw new Error(`customWorkers.${worker}.baseUrl must use http or https.`);
        }
        resolveCustomWorkerValue(worker, "model", config.model, env);
        if (config.apiKey !== undefined) {
            resolveCustomWorkerValue(worker, "apiKey", config.apiKey, env);
        }
        for (const [headerName, value] of Object.entries(config.headers ?? {})) {
            resolveCustomWorkerValue(worker, `headers.${headerName}`, value, env);
        }
        if (config.requestParams !== undefined) {
            resolveCustomWorkerJsonValue(worker, "requestParams", config.requestParams, env);
        }
        return {
            name,
            status: "ok",
            message: `Custom worker ${worker} static configuration is valid.`,
        };
    }
    catch (error) {
        return {
            name,
            status: "fail",
            message: error instanceof Error ? error.message : String(error),
        };
    }
}
function resolveCustomWorkerValue(worker, field, value, env) {
    let resolved;
    try {
        resolved = (0, env_template_1.resolveConfigEnvTemplate)(value, env);
    }
    catch (error) {
        if (error instanceof env_template_1.MissingConfigEnvTemplateValueError) {
            throw new Error(`customWorkers.${worker}.${field} references missing environment variable: ${error.envName}`);
        }
        if (error instanceof env_template_1.EmptyConfigEnvTemplateValueError) {
            throw new Error(`customWorkers.${worker}.${field} references empty environment variable: ${error.envName}`);
        }
        if (error instanceof env_template_1.InvalidConfigEnvTemplateError) {
            throw new Error(`customWorkers.${worker}.${field} has invalid environment template: ${error.expression}`);
        }
        throw error;
    }
    if (resolved.trim().length === 0) {
        throw new Error(`customWorkers.${worker}.${field} resolved to an empty value.`);
    }
    return resolved;
}
function resolveCustomWorkerJsonValue(worker, field, value, env) {
    if (typeof value === "string") {
        resolveCustomWorkerJsonString(worker, field, value, env);
        return;
    }
    if (Array.isArray(value)) {
        for (const [index, item] of value.entries()) {
            resolveCustomWorkerJsonValue(worker, `${field}[${index}]`, item, env);
        }
        return;
    }
    if (value !== null && typeof value === "object") {
        for (const [key, item] of Object.entries(value)) {
            resolveCustomWorkerJsonValue(worker, `${field}.${key}`, item, env);
        }
    }
}
function resolveCustomWorkerJsonString(worker, field, value, env) {
    try {
        (0, env_template_1.resolveConfigEnvTemplate)(value, env);
    }
    catch (error) {
        if (error instanceof env_template_1.MissingConfigEnvTemplateValueError) {
            throw new Error(`customWorkers.${worker}.${field} references missing environment variable: ${error.envName}`);
        }
        if (error instanceof env_template_1.EmptyConfigEnvTemplateValueError) {
            throw new Error(`customWorkers.${worker}.${field} references empty environment variable: ${error.envName}`);
        }
        if (error instanceof env_template_1.InvalidConfigEnvTemplateError) {
            throw new Error(`customWorkers.${worker}.${field} has invalid environment template: ${error.expression}`);
        }
        throw error;
    }
}
async function checkPiWorkerRuntime(locale, runtimeAvailabilityCheck) {
    const name = (0, check_names_1.getDoctorProviderCheckName)("Pi custom worker runtime", locale);
    try {
        await runtimeAvailabilityCheck(locale);
        return {
            name,
            status: "ok",
            message: "Pi custom worker runtime is available.",
        };
    }
    catch (error) {
        return {
            name,
            status: "fail",
            message: error instanceof Error ? error.message : String(error),
        };
    }
}
function checkPiMcpAdapterPackage(locale) {
    const name = (0, check_names_1.getDoctorProviderCheckName)("pi-mcp-adapter", locale);
    try {
        const extensionPaths = (0, pi_worker_runtime_1.resolvePiMcpAdapterExtensionPaths)();
        for (const extensionPath of extensionPaths) {
            (0, node_fs_1.readFileSync)(extensionPath, "utf8");
        }
        return {
            name,
            status: "ok",
            message: "pi-mcp-adapter declares readable Pi extensions.",
        };
    }
    catch (error) {
        return {
            name,
            status: "fail",
            message: error instanceof Error ? error.message : String(error),
        };
    }
}
async function checkPiMcpConfigFiles(cwd, locale) {
    const name = (0, check_names_1.getDoctorProviderCheckName)("custom worker MCP", locale);
    const configPaths = [
        node_path_1.default.join(cwd, ".mcp.json"),
        node_path_1.default.join(cwd, ".pi", "mcp.json"),
    ];
    for (const configPath of configPaths) {
        try {
            await (0, promises_1.access)(configPath);
        }
        catch {
            continue;
        }
        try {
            JSON.parse(await (0, promises_1.readFile)(configPath, "utf8"));
        }
        catch (error) {
            return {
                name,
                status: "fail",
                message: error instanceof Error
                    ? `Unable to read ${configPath}: ${error.message}`
                    : `Unable to read ${configPath}: ${String(error)}`,
            };
        }
    }
    return {
        name,
        status: "ok",
        message: "Custom worker MCP project configuration is readable.",
    };
}
