export type ProviderId = 'xai' | 'opencode-go'

export type ProviderApiKeys = Partial<Record<ProviderId, string>>

export const AI_CREDENTIALS_KEY = 'ai.credentials'

export const SUPPORTED_PROVIDERS: ProviderId[] = ['opencode-go', 'xai']

export const PROVIDER_KEY_LABELS: Record<
  ProviderId,
  { label: string; hint: string; docsUrl?: string }
> = {
  'opencode-go': {
    label: 'OpenCode Go',
    hint: '從 opencode.ai/auth 訂閱 Go 方案後取得',
    docsUrl: 'https://opencode.ai/docs/go/',
  },
  xai: { label: 'Grok (xAI)', hint: 'xAI Console API key' },
}

export const PROVIDER_ORDER: ProviderId[] = [...SUPPORTED_PROVIDERS]

export const PROVIDER_OPTIONS = [
  {
    value: 'opencode-go' as const,
    label: 'OpenCode Go',
    models: [
      'deepseek-v4-flash',
      'deepseek-v4-pro',
      'glm-5.1',
      'kimi-k2.7-code',
      'kimi-k2.5',
      'qwen3.7-max',
    ],
  },
  { value: 'xai' as const, label: 'Grok (xAI)', models: ['grok-3', 'grok-3-fast', 'grok-2-1212'] },
] as const

export type AccountAiCredentials = {
  provider: ProviderId
  model: string
  research_provider?: ProviderId
  research_model?: string
  api_keys: ProviderApiKeys
}

export const DEFAULT_AI_CREDENTIALS: AccountAiCredentials = {
  provider: 'opencode-go',
  model: 'deepseek-v4-pro',
  research_provider: 'opencode-go',
  research_model: 'deepseek-v4-flash',
  api_keys: {},
}

export function isSupportedProvider(value: string | undefined | null): value is ProviderId {
  return value === 'xai' || value === 'opencode-go'
}

export function normalizeSupportedProvider(value: string | undefined | null): ProviderId {
  return isSupportedProvider(value) ? value : DEFAULT_AI_CREDENTIALS.provider
}

function modelsForProvider(provider: ProviderId): readonly string[] {
  return PROVIDER_OPTIONS.find((item) => item.value === provider)?.models ?? []
}

function normalizeModel(provider: ProviderId, model: string | undefined, fallback: string): string {
  const models = modelsForProvider(provider)
  if (model && models.includes(model)) return model
  return models[0] ?? fallback
}

export type ProviderSettingsInput = {
  provider?: string
  model?: string
  research_provider?: string
  research_model?: string
}

export function normalizeProviderSettings(
  settings: ProviderSettingsInput,
): Pick<AccountAiCredentials, 'provider' | 'model' | 'research_provider' | 'research_model'> {
  const provider = normalizeSupportedProvider(settings.provider)
  const researchProvider = normalizeSupportedProvider(settings.research_provider ?? provider)
  return {
    provider,
    model: normalizeModel(provider, settings.model, DEFAULT_AI_CREDENTIALS.model),
    research_provider: researchProvider,
    research_model: normalizeModel(
      researchProvider,
      settings.research_model,
      DEFAULT_AI_CREDENTIALS.research_model ?? DEFAULT_AI_CREDENTIALS.model,
    ),
  }
}

export function maskApiKey(key: string | undefined | null): string | null {
  if (!key) return null
  if (key.length <= 4) return '••••'
  return `••••${key.slice(-4)}`
}

export function isMaskedKey(value: string): boolean {
  return value.startsWith('••••')
}

export function getApiKeyStatus(keys: ProviderApiKeys): Record<ProviderId, boolean> {
  return PROVIDER_ORDER.reduce(
    (acc, id) => {
      acc[id] = !!keys[id]?.trim()
      return acc
    },
    {} as Record<ProviderId, boolean>,
  )
}

export function mergeProviderApiKeys(
  existing: ProviderApiKeys,
  incoming: ProviderApiKeys,
): ProviderApiKeys {
  const merged = { ...existing }
  for (const provider of PROVIDER_ORDER) {
    const value = incoming[provider]
    const trimmed = value?.trim()
    if (!trimmed || isMaskedKey(trimmed)) continue
    merged[provider] = trimmed
  }
  return merged
}

export function getMaskedProviderApiKeys(keys: ProviderApiKeys): ProviderApiKeys {
  return PROVIDER_ORDER.reduce((acc, id) => {
    const masked = maskApiKey(keys[id])
    if (masked) acc[id] = masked
    return acc
  }, {} as ProviderApiKeys)
}

export function parseAccountAiCredentials(raw: Record<string, unknown> | undefined): AccountAiCredentials {
  if (!raw || typeof raw !== 'object') return { ...DEFAULT_AI_CREDENTIALS, api_keys: {} }
  const apiKeys =
    raw.api_keys && typeof raw.api_keys === 'object'
      ? (raw.api_keys as ProviderApiKeys)
      : {}
  const normalized = normalizeProviderSettings({
    provider: typeof raw.provider === 'string' ? raw.provider : DEFAULT_AI_CREDENTIALS.provider,
    model: typeof raw.model === 'string' ? raw.model : DEFAULT_AI_CREDENTIALS.model,
    research_provider:
      typeof raw.research_provider === 'string'
        ? raw.research_provider
        : DEFAULT_AI_CREDENTIALS.research_provider,
    research_model:
      typeof raw.research_model === 'string'
        ? raw.research_model
        : DEFAULT_AI_CREDENTIALS.research_model,
  })
  return { ...normalized, api_keys: apiKeys }
}

export function buildAccountAiCredentialsPayload(
  current: AccountAiCredentials,
  keyInputs: ProviderApiKeys,
): AccountAiCredentials {
  const normalized = normalizeProviderSettings(current)
  return {
    ...normalized,
    api_keys: mergeProviderApiKeys(current.api_keys, keyInputs),
  }
}

export function memberAiSettingsPath(userId: string) {
  return `/api/v1/settings/user/${encodeURIComponent(userId)}/${encodeURIComponent(AI_CREDENTIALS_KEY)}`
}