import type { Locale, TranslationKey, Translations } from './types.js'
import { defaultLocale, locales } from './locales/index.js'

let currentLocale: Locale = defaultLocale

function currentTranslations(): Translations {
  return locales[currentLocale] ?? locales[defaultLocale]
}

const statusTextSets = (() => {
  const terminal = new Set<string>()
  const done = new Set<string>()
  const error = new Set<string>()
  const interrupted = new Set<string>()
  const awaitingPrefixes = new Set<string>()
  const interruptedMarkdownLines = new Set<string>()

  for (const locale of Object.keys(locales) as Locale[]) {
    const bundle = locales[locale] as any
    const status = bundle?.chatStatus ?? {}

    if (typeof status.done === 'string') {
      terminal.add(status.done)
      done.add(status.done)
    }
    if (typeof status.error === 'string') {
      terminal.add(status.error)
      error.add(status.error)
    }
    if (typeof status.interrupted === 'string') {
      terminal.add(status.interrupted)
      interrupted.add(status.interrupted)
    }
    if (typeof status.permissionDenied === 'string')
      error.add(status.permissionDenied)
    if (typeof status.resumingDenied === 'string')
      error.add(status.resumingDenied)

    if (typeof status.awaitingApprovalPrefix === 'string')
      awaitingPrefixes.add(status.awaitingApprovalPrefix)
    if (typeof status.awaitingAnswersPrefix === 'string')
      awaitingPrefixes.add(status.awaitingAnswersPrefix)
    if (typeof status.approvalPendingPrefix === 'string')
      awaitingPrefixes.add(status.approvalPendingPrefix)
    if (typeof status.autoApprovingPrefix === 'string')
      awaitingPrefixes.add(status.autoApprovingPrefix)

    if (typeof status.interruptedMarkdown === 'string')
      interruptedMarkdownLines.add(status.interruptedMarkdown)
  }

  return {
    terminal,
    done,
    error,
    interrupted,
    awaitingPrefixes,
    interruptedMarkdownLines,
  }
})()

export function getLocale(): Locale {
  return currentLocale
}

export function setLocale(locale: Locale): void {
  if (currentLocale !== locale)
    currentLocale = locale
}

export function normalizeLocale(input: unknown): Locale | null {
  const raw = String(input ?? '').trim()
  if (!raw)
    return null
  const base = raw.split('.')[0]?.replace('_', '-').trim().toLowerCase()
  if (!base)
    return null
  if (base === 'en' || base.startsWith('en-'))
    return 'en'
  if (base === 'zh' || base.startsWith('zh-'))
    return 'zh-CN'
  return null
}

export function resolveLocalePreference(
  opts?: Readonly<{
    explicit?: string | null | undefined
    saved?: string | null | undefined
    env?: Record<string, string | undefined>
  }>,
): Locale {
  const env
    = opts?.env
      ?? ((globalThis as any)?.process?.env as
      | Record<string, string | undefined>
      | undefined)
    ?? {}
  const fromExplicit = normalizeLocale(opts?.explicit)
  if (fromExplicit)
    return fromExplicit
  const fromSaved = normalizeLocale(opts?.saved)
  if (fromSaved)
    return fromSaved
  const fromEnv = normalizeLocale(
    env.DIMCODE_LANG ?? env.LC_ALL ?? env.LC_MESSAGES ?? env.LANG,
  )
  return fromEnv ?? defaultLocale
}

function readPath(obj: Record<string, any>, key: string): unknown {
  const parts = key.split('.')
  let cur: any = obj
  for (const part of parts) {
    if (!cur || typeof cur !== 'object')
      return undefined
    cur = cur[part]
  }
  return cur
}

function applyParams(
  template: string,
  params: Record<string, string | number>,
): string {
  let out = template
  for (const [key, value] of Object.entries(params))
    out = out.replace(new RegExp(`\\{${key}\\}`, 'g'), String(value))
  return out
}

export function t(
  key: TranslationKey,
  params?: Record<string, string | number>,
): string {
  const raw = readPath(currentTranslations() as any, key)
  const text = typeof raw === 'string' ? raw : key
  return params ? applyParams(text, params) : text
}

export function getTranslations(locale: Locale): Translations {
  return locales[locale] ?? locales[defaultLocale]
}

export function isTerminalStatusText(text: string): boolean {
  return statusTextSets.terminal.has(String(text ?? '').trim())
}

export function isDoneStatusText(text: string): boolean {
  return statusTextSets.done.has(String(text ?? '').trim())
}

export function isErrorStatusText(text: string): boolean {
  return statusTextSets.error.has(String(text ?? '').trim())
}

export function isInterruptedStatusText(text: string): boolean {
  return statusTextSets.interrupted.has(String(text ?? '').trim())
}

export function isAwaitingStatusText(text: string): boolean {
  const trimmed = String(text ?? '').trim()
  if (!trimmed)
    return false
  for (const prefix of statusTextSets.awaitingPrefixes) {
    if (prefix && trimmed.startsWith(prefix))
      return true
  }
  return false
}

export function isInterruptedMarkdownText(text: string): boolean {
  const raw = String(text ?? '')
  if (!raw)
    return false
  for (const line of statusTextSets.interruptedMarkdownLines) {
    if (line && raw.includes(line))
      return true
  }
  return false
}
