import type { AudioFormat, VoiceProviderKind } from "./types.ts";

declare const process: { env: Record<string, string | undefined> };

export interface McpEndpointConfig {
  name: string;
  mcpUrl: string;
  bearerToken?: string;
  requiresPhiTransport: boolean;
}

export interface VoiceAgentConfig {
  defaultVoiceProvider: VoiceProviderKind;
  voiceProviderFailover: boolean;
  openai: {
    apiKey?: string;
    model: string;
    realtimeUrl: string;
    voice: string;
    safetyIdentifierSecret?: string;
  };
  xai: {
    apiKey?: string;
    model: string;
    realtimeUrl: string;
    voice: string;
    phiAllowed: boolean;
  };
  audio: {
    ringCentralFormat: AudioFormat;
    providerFormat: AudioFormat;
  };
  mcp: {
    advancedmd: McpEndpointConfig;
    ringcentral: McpEndpointConfig;
    ringcentralAdmin: McpEndpointConfig;
  };
  scheduling: {
    maxConcurrentTransactions: number;
    amdLookupTimeoutMs: number;
  };
  ringCentralSip?: RingCentralSipConfig;
}

export interface RingCentralSipConfig {
  domain: string;
  outboundProxy: string;
  username: string;
  password: string;
  authorizationId: string;
  codec: "OPUS/16000" | "OPUS/48000/2" | "PCMU/8000";
  debug: boolean;
}

function env(name: string): string | undefined {
  const value = process.env[name]?.trim();
  return value ? value : undefined;
}

let mcpBearerLegacyWarned = false;
function legacyMcpBearer(): string | undefined {
  const value = env("MCP_BEARER_TOKEN");
  if (value && !mcpBearerLegacyWarned) {
    mcpBearerLegacyWarned = true;
    // eslint-disable-next-line no-console
    console.warn(
      "[voice-agent] MCP_BEARER_TOKEN is deprecated. Set per-endpoint tokens instead: " +
        "MCP_BEARER_TOKEN_ADVANCEDMD, MCP_BEARER_TOKEN_RINGCENTRAL, MCP_BEARER_TOKEN_RINGCENTRAL_ADMIN.",
    );
  }
  return value;
}

function endpointBearer(specificEnv: string): string | undefined {
  return env(specificEnv) ?? legacyMcpBearer();
}

// Test-only helper: resets the module-level dedupe flag so deprecation-warning
// tests can verify the warning actually fires from an isolated state.
// Do NOT use in production code paths — the dedupe is intentional in prod.
export function __resetMcpBearerWarnedForTest(): void {
  mcpBearerLegacyWarned = false;
}

export function loadVoiceAgentConfig(): VoiceAgentConfig {
  return {
    defaultVoiceProvider:
      (env("VOICE_PROVIDER") as VoiceProviderKind | undefined) ?? "openai_realtime",
    voiceProviderFailover: env("VOICE_PROVIDER_FAILOVER") === "1",
    openai: {
      apiKey: env("OPENAI_API_KEY"),
      model: env("OPENAI_REALTIME_MODEL") ?? "gpt-realtime",
      realtimeUrl: env("OPENAI_REALTIME_URL") ?? "wss://api.openai.com/v1/realtime",
      voice: env("OPENAI_REALTIME_VOICE") ?? "marin",
      safetyIdentifierSecret: env("OPENAI_SAFETY_IDENTIFIER_SECRET"),
    },
    xai: {
      apiKey: env("XAI_API_KEY"),
      model: env("XAI_VOICE_MODEL") ?? "grok-voice-think-fast-1.0",
      realtimeUrl: env("XAI_REALTIME_URL") ?? "wss://api.x.ai/v1/realtime",
      voice: env("XAI_VOICE") ?? "eve",
      phiAllowed: env("XAI_PHI_ALLOWED") === "1",
    },
    audio: {
      ringCentralFormat: { codec: "pcm16", sampleRateHz: 16000, channels: 1 },
      providerFormat: { codec: "pcm16", sampleRateHz: 24000, channels: 1 },
    },
    mcp: {
      advancedmd: {
        name: "advancedmd",
        mcpUrl: mcpUrl("ADVANCEDMD_MCP_URL", "/advancedmd/mcp"),
        bearerToken: endpointBearer("MCP_BEARER_TOKEN_ADVANCEDMD"),
        requiresPhiTransport: true,
      },
      ringcentral: {
        name: "ringcentral",
        mcpUrl: mcpUrl("RINGCENTRAL_MCP_URL", "/ringcentral/mcp"),
        bearerToken: endpointBearer("MCP_BEARER_TOKEN_RINGCENTRAL"),
        requiresPhiTransport: false,
      },
      ringcentralAdmin: {
        name: "ringcentral-admin",
        mcpUrl: mcpUrl("RINGCENTRAL_ADMIN_MCP_URL", "/ringcentral-admin/mcp"),
        bearerToken: endpointBearer("MCP_BEARER_TOKEN_RINGCENTRAL_ADMIN"),
        requiresPhiTransport: false,
      },
    },
    scheduling: {
      maxConcurrentTransactions: Number(env("AMD_MAX_CONCURRENT_WRITES") ?? "1"),
      amdLookupTimeoutMs: Number(env("AMD_LOOKUP_TIMEOUT_MS") ?? "6000"),
    },
    ringCentralSip:
      env("RINGCENTRAL_SIP_DOMAIN") &&
      env("RINGCENTRAL_SIP_OUTBOUND_PROXY") &&
      env("RINGCENTRAL_SIP_USERNAME") &&
      env("RINGCENTRAL_SIP_PASSWORD") &&
      env("RINGCENTRAL_SIP_AUTHORIZATION_ID")
        ? {
            domain: env("RINGCENTRAL_SIP_DOMAIN")!,
            outboundProxy: env("RINGCENTRAL_SIP_OUTBOUND_PROXY")!,
            username: env("RINGCENTRAL_SIP_USERNAME")!,
            password: env("RINGCENTRAL_SIP_PASSWORD")!,
            authorizationId: env("RINGCENTRAL_SIP_AUTHORIZATION_ID")!,
            codec: ringCentralCodec(env("RINGCENTRAL_SIP_CODEC")),
            debug: env("RINGCENTRAL_SIP_DEBUG") === "1",
          }
        : undefined,
  };
}

function mcpUrl(envName: string, path: string): string {
  const explicit = env(envName);
  if (explicit) return explicit;
  const base = env("CLAUDE_CLOUD_BASE");
  if (!base) {
    throw new Error(`CLAUDE_CLOUD_BASE or ${envName} is required for hosted MCP access.`);
  }
  return `${base.replace(/\/$/, "")}${path}`;
}

function ringCentralCodec(value: string | undefined): RingCentralSipConfig["codec"] {
  if (value === "OPUS/48000/2" || value === "PCMU/8000" || value === "OPUS/16000") {
    return value;
  }
  return "OPUS/16000";
}
