"use strict";
/**
 * WebSearch Routes - WebSearch configuration and status
 */
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = require("express");
const websearch_manager_1 = require("../../utils/websearch-manager");
const provider_secrets_1 = require("../../utils/websearch/provider-secrets");
const types_1 = require("../../utils/websearch/types");
const auth_middleware_1 = require("../middleware/auth-middleware");
const config_loader_facade_1 = require("../../config/config-loader-facade");
const router = (0, express_1.Router)();
const WEBSEARCH_LOCAL_ACCESS_ERROR = 'WebSearch endpoints require localhost access when dashboard auth is disabled.';
const DEFAULT_WEBSEARCH_MAX_RESULTS = 5;
const MAX_WEBSEARCH_MAX_RESULTS = 10;
function isWebSearchApiKeyProviderId(value) {
    return Object.prototype.hasOwnProperty.call(provider_secrets_1.WEBSEARCH_API_KEY_PROVIDERS, value);
}
function clampWebSearchMaxResults(value, fallback) {
    const candidate = Number.isFinite(value) ? value : fallback;
    const normalized = Number.isFinite(candidate) ? candidate : DEFAULT_WEBSEARCH_MAX_RESULTS;
    return Math.max(1, Math.min(MAX_WEBSEARCH_MAX_RESULTS, Math.floor(normalized)));
}
router.use((req, res, next) => {
    if ((0, auth_middleware_1.requireLocalAccessWhenAuthDisabled)(req, res, WEBSEARCH_LOCAL_ACCESS_ERROR)) {
        next();
    }
});
/**
 * GET /api/websearch - Get WebSearch configuration
 * Returns: normalized WebSearch configuration
 */
router.get('/', (_req, res) => {
    try {
        const config = (0, config_loader_facade_1.getWebSearchConfig)();
        res.json({
            ...config,
            apiKeys: (0, provider_secrets_1.getWebSearchApiKeyStates)(),
        });
    }
    catch (error) {
        res.status(500).json({ error: error.message });
    }
});
/**
 * PUT /api/websearch - Update WebSearch configuration
 * Body: WebSearchConfig fields (enabled, providers)
 */
router.put('/', (req, res) => {
    if (req.body === null ||
        req.body === undefined ||
        typeof req.body !== 'object' ||
        Array.isArray(req.body)) {
        res.status(400).json({ error: 'Invalid request body. Must be an object.' });
        return;
    }
    const { enabled, providers, apiKeys } = req.body;
    // Validate enabled
    if (enabled !== undefined && typeof enabled !== 'boolean') {
        res.status(400).json({ error: 'Invalid value for enabled. Must be a boolean.' });
        return;
    }
    // Validate providers if specified
    if (providers !== undefined &&
        (providers === null || Array.isArray(providers) || typeof providers !== 'object')) {
        res.status(400).json({ error: 'Invalid value for providers. Must be an object.' });
        return;
    }
    if (providers?.searxng?.url !== undefined && typeof providers.searxng.url !== 'string') {
        res.status(400).json({ error: 'Invalid value for providers.searxng.url. Must be a string.' });
        return;
    }
    const normalizedSearxngUrl = providers?.searxng?.url !== undefined
        ? (0, types_1.normalizeSearxngBaseUrl)(providers.searxng.url)
        : undefined;
    if (providers?.searxng?.url !== undefined && normalizedSearxngUrl === null) {
        res.status(400).json({
            error: 'Invalid value for providers.searxng.url. Must be an http(s) base URL without credentials, query, or hash.',
        });
        return;
    }
    if (providers?.searxng?.max_results !== undefined &&
        (typeof providers.searxng.max_results !== 'number' ||
            !Number.isFinite(providers.searxng.max_results))) {
        res.status(400).json({
            error: 'Invalid value for providers.searxng.max_results. Must be a number.',
        });
        return;
    }
    if (apiKeys !== undefined &&
        (apiKeys === null || Array.isArray(apiKeys) || typeof apiKeys !== 'object')) {
        res.status(400).json({ error: 'Invalid value for apiKeys. Must be an object.' });
        return;
    }
    if (apiKeys) {
        for (const [providerId, value] of Object.entries(apiKeys)) {
            if (!isWebSearchApiKeyProviderId(providerId)) {
                res.status(400).json({ error: `Unsupported WebSearch provider: ${providerId}` });
                return;
            }
            if (value !== null && value !== undefined && typeof value !== 'string') {
                res.status(400).json({ error: `Invalid value for ${providerId} API key` });
                return;
            }
        }
    }
    try {
        (0, config_loader_facade_1.mutateConfig)((config) => {
            const existingSearxngUrl = (0, types_1.normalizeSearxngBaseUrl)(config.websearch?.providers?.searxng?.url) ?? '';
            config.websearch = {
                enabled: enabled ?? config.websearch?.enabled ?? true,
                providers: providers
                    ? {
                        exa: {
                            enabled: providers.exa?.enabled ?? config.websearch?.providers?.exa?.enabled ?? false,
                            max_results: providers.exa?.max_results ?? config.websearch?.providers?.exa?.max_results ?? 5,
                        },
                        tavily: {
                            enabled: providers.tavily?.enabled ??
                                config.websearch?.providers?.tavily?.enabled ??
                                false,
                            max_results: providers.tavily?.max_results ??
                                config.websearch?.providers?.tavily?.max_results ??
                                5,
                        },
                        duckduckgo: {
                            enabled: providers.duckduckgo?.enabled ??
                                config.websearch?.providers?.duckduckgo?.enabled ??
                                true,
                            max_results: providers.duckduckgo?.max_results ??
                                config.websearch?.providers?.duckduckgo?.max_results ??
                                5,
                        },
                        brave: {
                            enabled: providers.brave?.enabled ?? config.websearch?.providers?.brave?.enabled ?? false,
                            max_results: providers.brave?.max_results ??
                                config.websearch?.providers?.brave?.max_results ??
                                5,
                        },
                        searxng: {
                            enabled: providers.searxng?.enabled ??
                                config.websearch?.providers?.searxng?.enabled ??
                                false,
                            url: normalizedSearxngUrl ?? existingSearxngUrl,
                            max_results: clampWebSearchMaxResults(providers.searxng?.max_results, config.websearch?.providers?.searxng?.max_results ?? DEFAULT_WEBSEARCH_MAX_RESULTS),
                        },
                        gemini: {
                            enabled: providers.gemini?.enabled ??
                                config.websearch?.providers?.gemini?.enabled ??
                                false,
                            model: providers.gemini?.model ??
                                config.websearch?.providers?.gemini?.model ??
                                'gemini-2.5-flash',
                            timeout: providers.gemini?.timeout ?? config.websearch?.providers?.gemini?.timeout ?? 55,
                        },
                        grok: {
                            enabled: providers.grok?.enabled ?? config.websearch?.providers?.grok?.enabled ?? false,
                            timeout: providers.grok?.timeout ?? config.websearch?.providers?.grok?.timeout ?? 55,
                        },
                        opencode: {
                            enabled: providers.opencode?.enabled ??
                                config.websearch?.providers?.opencode?.enabled ??
                                false,
                            model: providers.opencode?.model ??
                                config.websearch?.providers?.opencode?.model ??
                                'opencode/grok-code',
                            timeout: providers.opencode?.timeout ??
                                config.websearch?.providers?.opencode?.timeout ??
                                60,
                        },
                    }
                    : config.websearch?.providers,
            };
            if (apiKeys) {
                config.global_env = {
                    enabled: config.global_env?.enabled ?? true,
                    env: (0, provider_secrets_1.applyWebSearchApiKeyUpdates)(config.global_env?.env ?? {}, apiKeys),
                };
            }
        });
        res.json({
            success: true,
            websearch: {
                ...(0, config_loader_facade_1.getWebSearchConfig)(),
                apiKeys: (0, provider_secrets_1.getWebSearchApiKeyStates)(),
            },
        });
    }
    catch (error) {
        res.status(500).json({ error: error.message });
    }
});
/**
 * GET /api/websearch/status - Get WebSearch status
 * Returns: provider readiness + normalized provider status list
 */
router.get('/status', (_req, res) => {
    try {
        const readiness = (0, websearch_manager_1.getWebSearchReadiness)();
        const providers = (0, websearch_manager_1.getWebSearchCliProviders)();
        res.json({
            providers,
            readiness: {
                status: readiness.readiness,
                message: readiness.message,
            },
        });
    }
    catch (error) {
        res.status(500).json({ error: error.message });
    }
});
exports.default = router;
//# sourceMappingURL=websearch-routes.js.map