export const runtimeConfigDefaults = {
    runtime: {
        companionChatLimiter: {
            perSessionLimit: 10,
        },
        eventBus: {
            maxListeners: 100,
        },
    },
    batch: {
        mode: 'off',
        fallback: 'live',
        queueBackend: 'local',
        tickIntervalMs: 60_000,
        maxDelayMs: 5 * 60 * 1000,
        maxJobsPerProviderBatch: 100,
        maxQueuePayloadBytes: 16 * 1024,
        maxQueueMessagesPerDay: 1_000,
    },
    cloudflare: {
        enabled: false,
        freeTierMode: true,
        accountId: '',
        apiTokenRef: '',
        zoneId: '',
        zoneName: '',
        workerName: 'goodvibes-batch-worker',
        workerSubdomain: '',
        workerHostname: '',
        workerBaseUrl: '',
        daemonBaseUrl: '',
        daemonHostname: '',
        workerTokenRef: '',
        workerClientTokenRef: '',
        workerCron: '*/5 * * * *',
        queueName: 'goodvibes-batch',
        deadLetterQueueName: 'goodvibes-batch-dlq',
        tunnelName: 'goodvibes-daemon',
        tunnelId: '',
        tunnelTokenRef: '',
        accessAppId: '',
        accessServiceTokenId: '',
        accessServiceTokenRef: '',
        kvNamespaceName: 'goodvibes-runtime',
        kvNamespaceId: '',
        durableObjectNamespaceName: 'GoodVibesCoordinator',
        durableObjectNamespaceId: '',
        r2BucketName: 'goodvibes-artifacts',
        secretsStoreName: 'goodvibes',
        secretsStoreId: '',
        maxQueueOpsPerDay: 10_000,
    },
    telemetry: {
        includeRawPrompts: false,
    },
    automation: {
        enabled: false,
        maxConcurrentRuns: 4,
        runHistoryLimit: 100,
        defaultTimeoutMs: 15 * 60 * 1000,
        catchUpWindowMinutes: 30,
        failureCooldownMs: 5 * 60 * 1000,
        deleteAfterRun: false,
    },
    controlPlane: {
        enabled: false,
        hostMode: 'local',
        host: '127.0.0.1',
        port: 3421,
        baseUrl: 'http://127.0.0.1:3421',
        streamMode: 'sse',
        allowRemote: false,
        trustProxy: false,
        openaiCompatible: {
            enabled: true,
            pathPrefix: '/v1',
        },
        tls: {
            mode: 'off',
            certFile: '',
            keyFile: '',
        },
    },
    httpListener: {
        hostMode: 'local',
        host: '127.0.0.1',
        port: 3422,
        trustProxy: false,
        tls: {
            mode: 'off',
            certFile: '',
            keyFile: '',
        },
    },
    web: {
        enabled: false,
        hostMode: 'local',
        host: '127.0.0.1',
        port: 3423,
        publicBaseUrl: 'http://127.0.0.1:3423',
        staticAssetsDir: 'dist/web',
    },
    watchers: {
        enabled: false,
        pollIntervalMs: 60_000,
        heartbeatIntervalMs: 15_000,
        recoveryWindowMinutes: 10,
    },
    service: {
        enabled: false,
        autostart: false,
        restartOnFailure: true,
        platform: 'auto',
        serviceName: 'goodvibes',
        logPath: '',
    },
    network: {
        outboundTls: {
            mode: 'bundled',
            customCaFile: '',
            customCaDir: '',
            allowInsecureLocalhost: false,
        },
        remoteFetch: {
            allowPrivateHosts: false,
        },
    },
};
export const runtimePrimaryConfigSettings = [
    {
        key: 'automation.enabled',
        type: 'boolean',
        default: false,
        description: 'Enable the automation subsystem',
    },
    {
        key: 'automation.maxConcurrentRuns',
        type: 'number',
        default: 4,
        description: 'Maximum automation runs that may execute concurrently',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 64,
    },
    {
        key: 'automation.runHistoryLimit',
        type: 'number',
        default: 100,
        description: 'Maximum run history entries retained per automation job',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 5000,
    },
    {
        key: 'automation.defaultTimeoutMs',
        type: 'number',
        default: 15 * 60 * 1000,
        description: 'Default execution timeout for automation runs in milliseconds',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1_000 && v <= 24 * 60 * 60 * 1000,
    },
    {
        key: 'automation.catchUpWindowMinutes',
        type: 'number',
        default: 30,
        description: 'How long after startup the engine should catch up missed runs',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 0 && v <= 24 * 60,
    },
    {
        key: 'automation.failureCooldownMs',
        type: 'number',
        default: 5 * 60 * 1000,
        description: 'Cooldown applied after a failed automation run before retrying',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 0 && v <= 24 * 60 * 60 * 1000,
    },
    {
        key: 'automation.deleteAfterRun',
        type: 'boolean',
        default: false,
        description: 'Delete one-shot automation jobs after their first successful run',
    },
    {
        key: 'controlPlane.enabled',
        type: 'boolean',
        default: false,
        description: 'Enable the shared gateway/control-plane service',
    },
    {
        key: 'controlPlane.hostMode',
        type: 'enum',
        default: 'local',
        description: 'Network binding mode: local (127.0.0.1, default port), network (0.0.0.0, default port), custom (editable host and port)',
        enumValues: ['local', 'network', 'custom'],
    },
    {
        key: 'controlPlane.host',
        type: 'string',
        default: '127.0.0.1',
        description: 'Bind host for the control-plane HTTP server',
    },
    {
        key: 'controlPlane.port',
        type: 'number',
        default: 3421,
        description: 'Bind port for the control-plane HTTP server',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 65535,
    },
    {
        key: 'controlPlane.baseUrl',
        type: 'string',
        default: 'http://127.0.0.1:3421',
        description: 'Public base URL used by route bindings and link generation',
    },
    {
        key: 'controlPlane.streamMode',
        type: 'enum',
        default: 'sse',
        description: 'Live update stream mode for control-plane clients',
        enumValues: ['sse', 'websocket', 'both'],
    },
    {
        key: 'controlPlane.allowRemote',
        type: 'boolean',
        default: false,
        description: 'Allow remote clients to connect to the control plane',
    },
    {
        key: 'controlPlane.trustProxy',
        type: 'boolean',
        default: false,
        description: 'Trust proxy forwarding headers such as x-forwarded-for for the control plane',
    },
    {
        key: 'controlPlane.openaiCompatible.enabled',
        type: 'boolean',
        default: true,
        description: 'Expose OpenAI-compatible /v1/models and /v1/chat/completions routes on the authenticated daemon',
    },
    {
        key: 'controlPlane.openaiCompatible.pathPrefix',
        type: 'string',
        default: '/v1',
        description: 'Path prefix for the daemon OpenAI-compatible routes',
        validate: (v) => typeof v === 'string' && v.startsWith('/') && !v.includes('..'),
    },
    {
        key: 'controlPlane.tls.mode',
        type: 'enum',
        default: 'off',
        description: 'TLS mode for the control-plane HTTP server',
        enumValues: ['off', 'proxy', 'direct'],
    },
    {
        key: 'controlPlane.tls.certFile',
        type: 'string',
        default: '',
        description: 'Certificate chain PEM path for direct control-plane TLS (empty = ~/.goodvibes/certs/fullchain.pem)',
    },
    {
        key: 'controlPlane.tls.keyFile',
        type: 'string',
        default: '',
        description: 'Private key PEM path for direct control-plane TLS (empty = ~/.goodvibes/certs/privkey.pem)',
    },
    {
        key: 'httpListener.hostMode',
        type: 'enum',
        default: 'local',
        description: 'Network binding mode: local (127.0.0.1, default port), network (0.0.0.0, default port), custom (editable host and port)',
        enumValues: ['local', 'network', 'custom'],
    },
    {
        key: 'httpListener.host',
        type: 'string',
        default: '127.0.0.1',
        description: 'Bind host for the webhook HTTP listener',
    },
    {
        key: 'httpListener.port',
        type: 'number',
        default: 3422,
        description: 'Bind port for the webhook HTTP listener',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 65535,
    },
    {
        key: 'httpListener.trustProxy',
        type: 'boolean',
        default: false,
        description: 'Trust proxy forwarding headers such as x-forwarded-for for the webhook listener',
    },
    {
        key: 'httpListener.tls.mode',
        type: 'enum',
        default: 'off',
        description: 'TLS mode for the webhook HTTP listener',
        enumValues: ['off', 'proxy', 'direct'],
    },
    {
        key: 'httpListener.tls.certFile',
        type: 'string',
        default: '',
        description: 'Certificate chain PEM path for direct webhook-listener TLS (empty = ~/.goodvibes/certs/fullchain.pem)',
    },
    {
        key: 'httpListener.tls.keyFile',
        type: 'string',
        default: '',
        description: 'Private key PEM path for direct webhook-listener TLS (empty = ~/.goodvibes/certs/privkey.pem)',
    },
    {
        key: 'web.enabled',
        type: 'boolean',
        default: false,
        description: 'Enable the browser-based operator surface',
    },
    {
        key: 'web.hostMode',
        type: 'enum',
        default: 'local',
        description: 'Network binding mode: local (127.0.0.1, default port), network (0.0.0.0, default port), custom (editable host and port)',
        enumValues: ['local', 'network', 'custom'],
    },
    {
        key: 'web.host',
        type: 'string',
        default: '127.0.0.1',
        description: 'Bind host for the web surface',
    },
    {
        key: 'web.port',
        type: 'number',
        default: 3423,
        description: 'Bind port for the web surface',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 65535,
    },
    {
        key: 'web.publicBaseUrl',
        type: 'string',
        default: 'http://127.0.0.1:3423',
        description: 'Public base URL for web links and ntfy/notification deep links',
    },
    {
        key: 'web.staticAssetsDir',
        type: 'string',
        default: 'dist/web',
        description: 'Static asset directory for the embedded web surface',
    },
];
export const runtimeSecondaryConfigSettings = [
    {
        key: 'watchers.enabled',
        type: 'boolean',
        default: false,
        description: 'Enable managed watcher/listener services',
    },
    {
        key: 'watchers.pollIntervalMs',
        type: 'number',
        default: 60_000,
        description: 'Polling interval for watcher sources in milliseconds',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1_000 && v <= 24 * 60 * 60 * 1000,
    },
    {
        key: 'watchers.heartbeatIntervalMs',
        type: 'number',
        default: 15_000,
        description: 'Heartbeat interval for watcher services in milliseconds',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1_000 && v <= 60 * 60 * 1000,
    },
    {
        key: 'watchers.recoveryWindowMinutes',
        type: 'number',
        default: 10,
        description: 'Recovery window for watcher restart and missed-event catch-up',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 0 && v <= 24 * 60,
    },
    {
        key: 'service.enabled',
        type: 'boolean',
        default: false,
        description: 'Enable service-install and daemon-management features',
    },
    {
        key: 'service.autostart',
        type: 'boolean',
        default: false,
        description: 'Start Goodvibes automatically when the host boots or logs in',
    },
    {
        key: 'service.restartOnFailure',
        type: 'boolean',
        default: true,
        description: 'Restart the service automatically after failure',
    },
    {
        key: 'service.platform',
        type: 'enum',
        default: 'auto',
        description: 'Target service manager platform',
        enumValues: ['auto', 'systemd', 'launchd', 'windows', 'manual'],
    },
    {
        key: 'service.serviceName',
        type: 'string',
        default: 'goodvibes',
        description: 'Service name used for host integration and install scripts',
    },
    {
        key: 'service.logPath',
        type: 'string',
        default: '',
        description: 'File path for daemon/service logs (empty = platform default under the configured service directory)',
    },
    {
        key: 'network.outboundTls.mode',
        type: 'enum',
        default: 'bundled',
        description: 'Outbound HTTPS trust mode for Bun fetch-based network calls',
        enumValues: ['bundled', 'bundled+custom', 'custom'],
    },
    {
        key: 'network.outboundTls.customCaFile',
        type: 'string',
        default: '',
        description: 'Additional PEM file to trust for outbound HTTPS when using bundled+custom or custom mode',
    },
    {
        key: 'network.outboundTls.customCaDir',
        type: 'string',
        default: '',
        description: 'Directory of PEM/CRT/CER files to trust for outbound HTTPS when using bundled+custom or custom mode',
    },
    {
        key: 'network.outboundTls.allowInsecureLocalhost',
        type: 'boolean',
        default: false,
        description: 'Allow self-signed HTTPS only for localhost/loopback outbound requests',
    },
    {
        key: 'network.remoteFetch.allowPrivateHosts',
        type: 'boolean',
        default: false,
        description: 'Allow explicit admin-approved remote fetches from private, localhost, or metadata hosts for artifacts and ingest flows',
    },
    {
        key: 'runtime.companionChatLimiter.perSessionLimit',
        type: 'number',
        default: 10,
        description: 'Max companion chat messages per 60-second window per session. ' +
            'Overrides the GOODVIBES_CHAT_LIMITER_THRESHOLD env var (env is read once at daemon startup; ' +
            'this config key is read on each check() call and takes precedence when set to a positive integer).',
    },
    {
        key: 'runtime.eventBus.maxListeners',
        type: 'number',
        default: 100,
        description: 'Maximum number of listeners per event channel (per-type and per-domain) before a warning is emitted in production ' +
            'or a RangeError is thrown in development mode. Raise this only if you have verified there is no subscriber leak.',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 100_000,
    },
    {
        key: 'telemetry.includeRawPrompts',
        type: 'boolean',
        default: false,
        description: 'When false (default), turn emitters emit a redacted prompt summary {length, sha256, first100chars} instead of raw prompt/response content. ' +
            'Set to true ONLY for debugging in non-production environments — raw prompts may contain PII, secrets, or proprietary data. ' +
            'When true at startup, a WARN log is emitted to make the configuration visible to ops.',
    },
    {
        key: 'batch.mode',
        type: 'enum',
        default: 'off',
        description: 'Daemon provider Batch API mode: off, explicit per request, or eligible-by-default for batch-capable daemon requests',
        enumValues: ['off', 'explicit', 'eligible-by-default'],
    },
    {
        key: 'batch.fallback',
        type: 'enum',
        default: 'live',
        description: 'Fallback behavior when a batch-requested job is not eligible: live allows callers to choose live execution, fail rejects the batch job',
        enumValues: ['live', 'fail'],
    },
    {
        key: 'batch.queueBackend',
        type: 'enum',
        default: 'local',
        description: 'Queue backend for daemon batch signals. local stores jobs under the daemon config directory; cloudflare requires cloudflare.enabled.',
        enumValues: ['local', 'cloudflare'],
    },
    {
        key: 'batch.tickIntervalMs',
        type: 'number',
        default: 60_000,
        description: 'Daemon-local batch scheduler tick interval in milliseconds',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 5_000 && v <= 60 * 60 * 1000,
    },
    {
        key: 'batch.maxDelayMs',
        type: 'number',
        default: 5 * 60 * 1000,
        description: 'Maximum time a queued local batch job should wait before the daemon submits its provider batch',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 0 && v <= 24 * 60 * 60 * 1000,
    },
    {
        key: 'batch.maxJobsPerProviderBatch',
        type: 'number',
        default: 100,
        description: 'Maximum SDK jobs grouped into a single upstream provider batch submission',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 100_000,
    },
    {
        key: 'batch.maxQueuePayloadBytes',
        type: 'number',
        default: 16 * 1024,
        description: 'Recommended maximum Cloudflare queue message payload size; queue messages should be signals, not full prompt archives',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 1024 && v <= 128 * 1024,
    },
    {
        key: 'batch.maxQueueMessagesPerDay',
        type: 'number',
        default: 1_000,
        description: 'SDK-side free-tier guardrail for Cloudflare queue message volume',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 0 && v <= 10_000_000,
    },
    {
        key: 'cloudflare.enabled',
        type: 'boolean',
        default: false,
        description: 'Enable optional Cloudflare Worker/Queue integration points. The daemon does not require Cloudflare when this is false.',
    },
    {
        key: 'cloudflare.freeTierMode',
        type: 'boolean',
        default: true,
        description: 'Prefer Cloudflare usage patterns that fit the free tier: small queue signals, local daemon storage, and bounded daily queue volume',
    },
    {
        key: 'cloudflare.accountId',
        type: 'string',
        default: '',
        description: 'Cloudflare account id used by SDK-owned Worker/Queue provisioning',
    },
    {
        key: 'cloudflare.apiTokenRef',
        type: 'string',
        default: '',
        description: 'GoodVibes secret reference for the Cloudflare API token. If empty, the SDK falls back to CLOUDFLARE_API_TOKEN.',
    },
    {
        key: 'cloudflare.zoneId',
        type: 'string',
        default: '',
        description: 'Optional Cloudflare zone id selected for SDK-managed DNS and Zero Trust Access hostnames',
    },
    {
        key: 'cloudflare.zoneName',
        type: 'string',
        default: '',
        description: 'Optional Cloudflare zone name selected during discovery/onboarding when zone id is not known yet',
    },
    {
        key: 'cloudflare.workerName',
        type: 'string',
        default: 'goodvibes-batch-worker',
        description: 'Cloudflare Worker script name managed by GoodVibes provisioning',
        validate: (v) => typeof v === 'string' && (/^[a-z0-9][a-z0-9-]{0,62}$/i.test(v) || v === ''),
    },
    {
        key: 'cloudflare.workerSubdomain',
        type: 'string',
        default: '',
        description: 'Cloudflare account workers.dev subdomain used to infer cloudflare.workerBaseUrl',
    },
    {
        key: 'cloudflare.workerHostname',
        type: 'string',
        default: '',
        description: 'Optional custom hostname for the GoodVibes Cloudflare Worker when DNS automation is enabled',
    },
    {
        key: 'cloudflare.workerBaseUrl',
        type: 'string',
        default: '',
        description: 'Optional deployed GoodVibes Cloudflare Worker base URL used by clients that proxy batch signals through Workers',
    },
    {
        key: 'cloudflare.daemonBaseUrl',
        type: 'string',
        default: '',
        description: 'Daemon origin URL the Cloudflare Worker or Tunnel uses for Worker-to-daemon batch calls',
    },
    {
        key: 'cloudflare.daemonHostname',
        type: 'string',
        default: '',
        description: 'Optional public daemon hostname managed through Cloudflare DNS, Tunnel, and Access provisioning',
    },
    {
        key: 'cloudflare.workerTokenRef',
        type: 'string',
        default: '',
        description: 'Optional GoodVibes secret reference for the Worker-to-daemon bearer token',
    },
    {
        key: 'cloudflare.workerClientTokenRef',
        type: 'string',
        default: '',
        description: 'Optional GoodVibes secret reference for the bearer token clients use when calling the Cloudflare Worker',
    },
    {
        key: 'cloudflare.workerCron',
        type: 'string',
        default: '*/5 * * * *',
        description: 'Cron trigger installed on the GoodVibes Cloudflare Worker for batch scheduler ticks',
    },
    {
        key: 'cloudflare.queueName',
        type: 'string',
        default: 'goodvibes-batch',
        description: 'Cloudflare Queue binding/name for GoodVibes batch job signals',
    },
    {
        key: 'cloudflare.deadLetterQueueName',
        type: 'string',
        default: 'goodvibes-batch-dlq',
        description: 'Cloudflare dead-letter queue binding/name for failed GoodVibes batch job signals',
    },
    {
        key: 'cloudflare.tunnelName',
        type: 'string',
        default: 'goodvibes-daemon',
        description: 'Zero Trust Tunnel name managed by GoodVibes provisioning when tunnel integration is enabled',
    },
    {
        key: 'cloudflare.tunnelId',
        type: 'string',
        default: '',
        description: 'Cloudflare Zero Trust Tunnel id selected or created by GoodVibes provisioning',
    },
    {
        key: 'cloudflare.tunnelTokenRef',
        type: 'string',
        default: '',
        description: 'GoodVibes secret reference for the cloudflared tunnel token generated by provisioning',
    },
    {
        key: 'cloudflare.accessAppId',
        type: 'string',
        default: '',
        description: 'Cloudflare Zero Trust Access application id protecting the GoodVibes daemon hostname',
    },
    {
        key: 'cloudflare.accessServiceTokenId',
        type: 'string',
        default: '',
        description: 'Cloudflare Zero Trust Access service token id created for GoodVibes daemon access',
    },
    {
        key: 'cloudflare.accessServiceTokenRef',
        type: 'string',
        default: '',
        description: 'GoodVibes secret reference storing Access service token client id/secret JSON',
    },
    {
        key: 'cloudflare.kvNamespaceName',
        type: 'string',
        default: 'goodvibes-runtime',
        description: 'Cloudflare KV namespace name used for optional edge runtime state',
    },
    {
        key: 'cloudflare.kvNamespaceId',
        type: 'string',
        default: '',
        description: 'Cloudflare KV namespace id used for the GoodVibes Worker binding',
    },
    {
        key: 'cloudflare.durableObjectNamespaceName',
        type: 'string',
        default: 'GoodVibesCoordinator',
        description: 'Cloudflare Durable Object class/namespace name used for optional edge coordination',
    },
    {
        key: 'cloudflare.durableObjectNamespaceId',
        type: 'string',
        default: '',
        description: 'Cloudflare Durable Object namespace id discovered after Worker migration',
    },
    {
        key: 'cloudflare.r2BucketName',
        type: 'string',
        default: 'goodvibes-artifacts',
        description: 'Cloudflare R2 Standard bucket name used for optional GoodVibes artifacts',
    },
    {
        key: 'cloudflare.secretsStoreName',
        type: 'string',
        default: 'goodvibes',
        description: 'Cloudflare Secrets Store name managed by optional GoodVibes provisioning',
    },
    {
        key: 'cloudflare.secretsStoreId',
        type: 'string',
        default: '',
        description: 'Cloudflare Secrets Store id selected or created by GoodVibes provisioning',
    },
    {
        key: 'cloudflare.maxQueueOpsPerDay',
        type: 'number',
        default: 10_000,
        description: 'Free-tier queue operation budget used by clients to warn before Cloudflare queue usage exceeds the intended budget',
        validate: (v) => typeof v === 'number' && Number.isInteger(v) && v >= 0 && v <= 10_000_000,
    },
];
