import { isEnvTruthy } from 'src/utils/envUtils.js'

// Default to prod config, override with test/staging if enabled
type OauthConfigType = 'prod' | 'staging' | 'local'

function getOauthConfigType(): OauthConfigType {
  if (process.env.USER_TYPE === 'ant') {
    if (isEnvTruthy(process.env.USE_LOCAL_OAUTH)) {
      return 'local'
    }
    if (isEnvTruthy(process.env.USE_STAGING_OAUTH)) {
      return 'staging'
    }
  }
  return 'prod'
}

export function fileSuffixForOauthConfig(): string {
  if (process.env.CLAUDE_CODE_CUSTOM_OAUTH_URL) {
    return '-custom-oauth'
  }
  switch (getOauthConfigType()) {
    case 'local':
      return '-local-oauth'
    case 'staging':
      return '-staging-oauth'
    case 'prod':
      // No suffix for production config
      return ''
  }
}

export const CLAUDE_AI_INFERENCE_SCOPE = 'user:inference' as const
export const CLAUDE_AI_PROFILE_SCOPE = 'user:profile' as const
const CONSOLE_SCOPE = 'org:create_api_key' as const
export const OAUTH_BETA_HEADER = 'oauth-2025-04-20' as const

// Console OAuth scopes - for API key creation via Console
export const CONSOLE_OAUTH_SCOPES = [
  CONSOLE_SCOPE,
  CLAUDE_AI_PROFILE_SCOPE,
] as const

// Claude.ai OAuth scopes - for Claude.ai subscribers (Pro/Max/Team/Enterprise)
export const CLAUDE_AI_OAUTH_SCOPES = [
  CLAUDE_AI_PROFILE_SCOPE,
  CLAUDE_AI_INFERENCE_SCOPE,
  'user:sessions:claude_code',
  'user:mcp_servers',
  'user:file_upload',
] as const

// All OAuth scopes - union of all scopes used in Claude CLI
// When logging in, request all scopes in order to handle both Console -> Claude.ai redirect
// Ensure that `OAuthConsentPage` in apps repo is kept in sync with this list.
export const ALL_OAUTH_SCOPES = Array.from(
  new Set([...CONSOLE_OAUTH_SCOPES, ...CLAUDE_AI_OAUTH_SCOPES]),
)

type OauthConfig = {
  BASE_API_URL: string
  CONSOLE_AUTHORIZE_URL: string
  CLAUDE_AI_AUTHORIZE_URL: string
  /**
   * The claude.ai web origin. Separate from CLAUDE_AI_AUTHORIZE_URL because
   * that now routes through claude.com/cai/* for attribution — deriving
   * .origin from it would give claude.com, breaking links to /code,
   * /settings/connectors, and other claude.ai web pages.
   */
  CLAUDE_AI_ORIGIN: string
  TOKEN_URL: string
  API_KEY_URL: string
  ROLES_URL: string
  CONSOLE_SUCCESS_URL: string
  CLAUDEAI_SUCCESS_URL: string
  MANUAL_REDIRECT_URL: string
  CLIENT_ID: string
  OAUTH_FILE_SUFFIX: string
  MCP_PROXY_URL: string
  MCP_PROXY_PATH: string
}

/** RiOS 睿思云静态站 / 登录页域名（无尾部斜杠）。可用 `RIOS_OAUTH_CLOUD_BASE` 覆盖。 */
function getRiOsOauthCloudBase(): string {
  return (
    process.env.RIOS_OAUTH_CLOUD_BASE?.replace(/\/$/, '') ??
    'https://cloud.rios.com.ai'
  )
}

/**
 * RiOS Express 后端（rios-api）根 URL，与静态站可不同。
 * 未设置时与 `RIOS_OAUTH_CLOUD_BASE` 相同；若 `cloud` 仅为 Blob 静态站，
 * POST `/v1/oauth/token` 会得到 405，此时必须设为容器应用上 `/api/health` 可用的根地址。
 */
function getRiOsOauthApiBase(): string {
  return (
    process.env.RIOS_OAUTH_API_BASE?.replace(/\/$/, '') ??
    getRiOsOauthCloudBase()
  )
}

/** 控制台登录入口（与浏览器内授权页一致） */
export function getRiOsCloudLoginUrl(): string {
  return `${getRiOsOauthCloudBase()}/index.html`
}

/**
 * OAuth loopback bind host and redirect_uri host (RFC 8252).
 * Default `127.0.0.1`. Set `RIOS_OAUTH_LOOPBACK_HOST=localhost` if your IdP only allows that hostname.
 */
export function getOAuthLoopbackHost(): string {
  const h = process.env.RIOS_OAUTH_LOOPBACK_HOST?.trim().toLowerCase()
  if (h === 'localhost' || h === '127.0.0.1') {
    return h
  }
  return '127.0.0.1'
}

/**
 * Use only RiOS Cloud `MANUAL_REDIRECT_URL` (no local loopback server).
 * After the browser shows the callback page, paste the **full address bar URL**
 * (or `code#state` if that is what RiOS shows) into the terminal.
 * Set `RIOS_OAUTH_USE_CLOUD_CALLBACK=1` when RiOS Cloud cannot redirect to 127.0.0.1.
 */
export function useCloudOAuthCallbackOnly(): boolean {
  return isEnvTruthy(process.env.RIOS_OAUTH_USE_CLOUD_CALLBACK)
}

/** 与 `buildRiOsProdOauthConfig` 一致，供判断是否睿思托管 IdP（持久化 OAuth、JWT 调网关等）。 */
export const RIOS_CODE_OAUTH_CLIENT_ID_PROD =
  '9d1c250a-e61b-44d9-88ed-5944d1962f5e' as const

/** 当前 OAuth 配置是否指向睿思云（含本地把 TOKEN_URL 指到 rios-api 的情况）。 */
export function isRiOsManagedOauthIssuer(): boolean {
  if (
    process.env.RIOS_OAUTH_API_BASE?.trim() ||
    process.env.RIOS_OAUTH_CLOUD_BASE?.trim()
  ) {
    return true
  }
  try {
    const c = getOauthConfig()
    return (
      c.CLIENT_ID === RIOS_CODE_OAUTH_CLIENT_ID_PROD ||
      c.TOKEN_URL.toLowerCase().includes('rios.com')
    )
  } catch {
    return false
  }
}

// Production OAuth — RiOS 睿思云（[RiOS Dashboard](https://cloud.rios.com.ai/index.html)）
function buildRiOsProdOauthConfig(): OauthConfig {
  const cloud = getRiOsOauthCloudBase()
  const api = getRiOsOauthApiBase()
  return {
    BASE_API_URL: api,
    CONSOLE_AUTHORIZE_URL: `${cloud}/index.html`,
    CLAUDE_AI_AUTHORIZE_URL: `${cloud}/index.html`,
    CLAUDE_AI_ORIGIN: cloud,
    TOKEN_URL: `${api}/v1/oauth/token`,
    API_KEY_URL: `${api}/api/oauth/claude_cli/create_api_key`,
    ROLES_URL: `${api}/api/oauth/claude_cli/roles`,
    CONSOLE_SUCCESS_URL: `${cloud}/index.html?flow=billing-return&app=rios-code`,
    CLAUDEAI_SUCCESS_URL: `${cloud}/index.html?flow=oauth-success&app=rios-code`,
    MANUAL_REDIRECT_URL: `${cloud}/oauth/code/callback`,
    CLIENT_ID: RIOS_CODE_OAUTH_CLIENT_ID_PROD,
    OAUTH_FILE_SUFFIX: '',
    MCP_PROXY_URL: 'https://mcp-proxy.anthropic.com',
    MCP_PROXY_PATH: '/v1/mcp/{server_id}',
  }
}

/**
 * Client ID Metadata Document URL for MCP OAuth (CIMD / SEP-991).
 * When an MCP auth server advertises client_id_metadata_document_supported: true,
 * RiOS Code uses this URL as its client_id instead of Dynamic Client Registration.
 * The URL must point to a JSON document hosted by Anthropic.
 * See: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00
 */
export const MCP_CLIENT_METADATA_URL =
  'https://cloud.rios.com.ai/oauth/rios-code-client-metadata'

// Staging OAuth configuration - only included in ant builds with staging flag
// Uses literal check for dead code elimination
const STAGING_OAUTH_CONFIG =
  process.env.USER_TYPE === 'ant'
    ? ({
        BASE_API_URL: 'https://api-staging.anthropic.com',
        CONSOLE_AUTHORIZE_URL:
          'https://platform.staging.ant.dev/oauth/authorize',
        CLAUDE_AI_AUTHORIZE_URL:
          'https://claude-ai.staging.ant.dev/oauth/authorize',
        CLAUDE_AI_ORIGIN: 'https://claude-ai.staging.ant.dev',
        TOKEN_URL: 'https://platform.staging.ant.dev/v1/oauth/token',
        API_KEY_URL:
          'https://api-staging.anthropic.com/api/oauth/claude_cli/create_api_key',
        ROLES_URL:
          'https://api-staging.anthropic.com/api/oauth/claude_cli/roles',
        CONSOLE_SUCCESS_URL:
          'https://platform.staging.ant.dev/buy_credits?returnUrl=/oauth/code/success%3Fapp%3Dclaude-code',
        CLAUDEAI_SUCCESS_URL:
          'https://platform.staging.ant.dev/oauth/code/success?app=claude-code',
        MANUAL_REDIRECT_URL:
          'https://platform.staging.ant.dev/oauth/code/callback',
        CLIENT_ID: '22422756-60c9-4084-8eb7-27705fd5cf9a',
        OAUTH_FILE_SUFFIX: '-staging-oauth',
        MCP_PROXY_URL: 'https://mcp-proxy-staging.anthropic.com',
        MCP_PROXY_PATH: '/v1/mcp/{server_id}',
      } as const)
    : undefined

// Three local dev servers: :8000 api-proxy (`api dev start -g ccr`),
// :4000 claude-ai frontend, :3000 Console frontend. Env vars let
// scripts/claude-localhost override if your layout differs.
function getLocalOauthConfig(): OauthConfig {
  const api =
    process.env.CLAUDE_LOCAL_OAUTH_API_BASE?.replace(/\/$/, '') ??
    'http://localhost:8000'
  const apps =
    process.env.CLAUDE_LOCAL_OAUTH_APPS_BASE?.replace(/\/$/, '') ??
    'http://localhost:4000'
  const consoleBase =
    process.env.CLAUDE_LOCAL_OAUTH_CONSOLE_BASE?.replace(/\/$/, '') ??
    'http://localhost:3000'
  return {
    BASE_API_URL: api,
    CONSOLE_AUTHORIZE_URL: `${consoleBase}/oauth/authorize`,
    CLAUDE_AI_AUTHORIZE_URL: `${apps}/oauth/authorize`,
    CLAUDE_AI_ORIGIN: apps,
    TOKEN_URL: `${api}/v1/oauth/token`,
    API_KEY_URL: `${api}/api/oauth/claude_cli/create_api_key`,
    ROLES_URL: `${api}/api/oauth/claude_cli/roles`,
    CONSOLE_SUCCESS_URL: `${consoleBase}/buy_credits?returnUrl=/oauth/code/success%3Fapp%3Dclaude-code`,
    CLAUDEAI_SUCCESS_URL: `${consoleBase}/oauth/code/success?app=claude-code`,
    MANUAL_REDIRECT_URL: `${consoleBase}/oauth/code/callback`,
    CLIENT_ID: '22422756-60c9-4084-8eb7-27705fd5cf9a',
    OAUTH_FILE_SUFFIX: '-local-oauth',
    MCP_PROXY_URL: 'http://localhost:8205',
    MCP_PROXY_PATH: '/v1/toolbox/shttp/mcp/{server_id}',
  }
}

// Allowed base URLs for CLAUDE_CODE_CUSTOM_OAUTH_URL override.
// Only FedStart/PubSec deployments are permitted to prevent OAuth tokens
// from being sent to arbitrary endpoints.
const ALLOWED_OAUTH_BASE_URLS = [
  'https://cloud.rios.com.ai',
  'https://beacon.claude-ai.staging.ant.dev',
  'https://claude.fedstart.com',
  'https://claude-staging.fedstart.com',
]

// Default to prod config, override with test/staging if enabled
export function getOauthConfig(): OauthConfig {
  let config: OauthConfig = (() => {
    switch (getOauthConfigType()) {
      case 'local':
        return getLocalOauthConfig()
      case 'staging':
        return STAGING_OAUTH_CONFIG ?? buildRiOsProdOauthConfig()
      case 'prod':
        return buildRiOsProdOauthConfig()
    }
  })()

  // Allow overriding all OAuth URLs to point to an approved FedStart deployment.
  // Only allowlisted base URLs are accepted to prevent credential leakage.
  const oauthBaseUrl = process.env.CLAUDE_CODE_CUSTOM_OAUTH_URL
  if (oauthBaseUrl) {
    const base = oauthBaseUrl.replace(/\/$/, '')
    if (!ALLOWED_OAUTH_BASE_URLS.includes(base)) {
      throw new Error(
        'CLAUDE_CODE_CUSTOM_OAUTH_URL is not an approved endpoint.',
      )
    }
    config = {
      ...config,
      BASE_API_URL: base,
      CONSOLE_AUTHORIZE_URL: `${base}/oauth/authorize`,
      CLAUDE_AI_AUTHORIZE_URL: `${base}/oauth/authorize`,
      CLAUDE_AI_ORIGIN: base,
      TOKEN_URL: `${base}/v1/oauth/token`,
      API_KEY_URL: `${base}/api/oauth/claude_cli/create_api_key`,
      ROLES_URL: `${base}/api/oauth/claude_cli/roles`,
      CONSOLE_SUCCESS_URL: `${base}/oauth/code/success?app=claude-code`,
      CLAUDEAI_SUCCESS_URL: `${base}/oauth/code/success?app=claude-code`,
      MANUAL_REDIRECT_URL: `${base}/oauth/code/callback`,
      OAUTH_FILE_SUFFIX: '-custom-oauth',
    }
  }

  // Allow CLIENT_ID override via environment variable (e.g., for Xcode integration)
  const clientIdOverride = process.env.CLAUDE_CODE_OAUTH_CLIENT_ID
  if (clientIdOverride) {
    config = {
      ...config,
      CLIENT_ID: clientIdOverride,
    }
  }

  return config
}
