import { ConfigManager } from '../infrastructure/ConfigManager';

import type { CliProviderId, TeamProviderId } from '@shared/types';

type RuntimeEnvProviderId = CliProviderId | TeamProviderId;

type AnthropicRuntimeBackendProviderId =
  | 'anthropic'
  | 'bedrock'
  | 'vertex'
  | 'foundry'
  | 'claude-platform-aws';

const PROVIDER_ROUTING_ENV_KEYS = [
  'CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST',
  'CLAUDE_CODE_ENTRY_PROVIDER',
  'CLAUDE_CODE_USE_OPENAI',
  'CLAUDE_CODE_USE_BEDROCK',
  'CLAUDE_CODE_USE_VERTEX',
  'CLAUDE_CODE_USE_FOUNDRY',
  'CLAUDE_CODE_USE_GEMINI',
] as const;

const BACKEND_SELECTION_ENV_KEYS = [
  'CLAUDE_CODE_GEMINI_BACKEND',
  'CLAUDE_CODE_CODEX_BACKEND',
] as const;

export function applyConfiguredRuntimeBackendsEnv(
  env: NodeJS.ProcessEnv,
  runtimeConfig = ConfigManager.getInstance().getConfig().runtime
): NodeJS.ProcessEnv {
  for (const key of BACKEND_SELECTION_ENV_KEYS) {
    env[key] = undefined;
  }

  env.CLAUDE_CODE_GEMINI_BACKEND = runtimeConfig.providerBackends.gemini;
  env.CLAUDE_CODE_CODEX_BACKEND = runtimeConfig.providerBackends.codex;
  return env;
}

function isTruthyEnvValue(value: string | undefined): boolean {
  const normalized = value?.trim().toLowerCase();
  return Boolean(normalized && normalized !== '0' && normalized !== 'false' && normalized !== 'no');
}

function resolveAnthropicRuntimeBackendFromEnv(
  env: NodeJS.ProcessEnv
): AnthropicRuntimeBackendProviderId {
  if (isTruthyEnvValue(env.CLAUDE_CODE_USE_BEDROCK)) {
    return 'bedrock';
  }
  if (isTruthyEnvValue(env.CLAUDE_CODE_USE_VERTEX)) {
    return 'vertex';
  }
  if (isTruthyEnvValue(env.CLAUDE_CODE_USE_FOUNDRY)) {
    return 'foundry';
  }
  if (env.ANTHROPIC_AWS_WORKSPACE_ID?.trim()) {
    return 'claude-platform-aws';
  }
  return 'anthropic';
}

function applyAnthropicRuntimeBackendEnv(
  env: NodeJS.ProcessEnv,
  backend: AnthropicRuntimeBackendProviderId
): void {
  if (backend === 'bedrock') {
    env.CLAUDE_CODE_USE_BEDROCK = '1';
  } else if (backend === 'vertex') {
    env.CLAUDE_CODE_USE_VERTEX = '1';
  } else if (backend === 'foundry') {
    env.CLAUDE_CODE_USE_FOUNDRY = '1';
  }
}

export function applyProviderRuntimeEnv(
  env: NodeJS.ProcessEnv,
  providerId: RuntimeEnvProviderId | undefined
): NodeJS.ProcessEnv {
  const resolvedProvider = resolveRuntimeProviderId(providerId);
  const anthropicBackend =
    resolvedProvider === 'anthropic' ? resolveAnthropicRuntimeBackendFromEnv(env) : 'anthropic';

  for (const key of PROVIDER_ROUTING_ENV_KEYS) {
    env[key] = undefined;
  }

  // Provider overrides must be positive pins. In dev and multimodel desktop
  // flows the host process can already be routed to codex or gemini, and the
  // child runtime reapplies settings.env after trust. Mark the env as
  // host-managed and set the exact entry provider so anthropic teammates do not
  // silently fall back into the host's current routing world.
  env.CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST = '1';
  env.CLAUDE_CODE_ENTRY_PROVIDER =
    resolvedProvider === 'anthropic' ? anthropicBackend : resolvedProvider;
  applyAnthropicRuntimeBackendEnv(env, anthropicBackend);

  return env;
}

export function resolveRuntimeProviderId(
  providerId: RuntimeEnvProviderId | undefined
): CliProviderId {
  if (providerId === 'codex' || providerId === 'gemini' || providerId === 'opencode') {
    return providerId;
  }

  return 'anthropic';
}

export function resolveTeamProviderId(providerId: TeamProviderId | undefined): TeamProviderId {
  return providerId === 'codex' || providerId === 'gemini' || providerId === 'opencode'
    ? providerId
    : 'anthropic';
}
