export class I18nTranslatorError extends Error {
  override readonly name: string = 'I18nTranslatorError'
  readonly _tag = 'I18nTranslatorError' as const
  constructor(readonly code: string, message: string) {
    super(message)
  }
}

export class UnknownLocaleError extends I18nTranslatorError {
  override readonly code: 'UNKNOWN_LOCALE' = 'UNKNOWN_LOCALE'
  override readonly name = 'UnknownLocaleError'
  constructor(readonly locale: string) {
    super('UNKNOWN_LOCALE', `locale '${locale}' is not active or does not exist`)
  }
}

export class SourceUnavailableError extends I18nTranslatorError {
  override readonly code: 'SOURCE_UNAVAILABLE' = 'SOURCE_UNAVAILABLE'
  override readonly name = 'SourceUnavailableError'
  constructor(
    readonly entityType: string,
    readonly entityId: string,
  ) {
    super(
      'SOURCE_UNAVAILABLE',
      `source text unavailable for ${entityType}/${entityId}`,
    )
  }
}

export class NoAdaptersConfiguredError extends I18nTranslatorError {
  override readonly code: 'NO_ADAPTERS_CONFIGURED' = 'NO_ADAPTERS_CONFIGURED'
  override readonly name = 'NoAdaptersConfiguredError'
  constructor() {
    super(
      'NO_ADAPTERS_CONFIGURED',
      'no AI adapters are configured; register at least one adapter via setAdapterFactories',
    )
  }
}

export function isI18nTranslatorError(e: unknown): e is I18nTranslatorError {
  return e instanceof Error && (e as { _tag?: unknown })._tag === 'I18nTranslatorError'
}

export function isUnknownLocaleError(e: unknown): e is UnknownLocaleError {
  return (
    isI18nTranslatorError(e) &&
    e.code === 'UNKNOWN_LOCALE' &&
    typeof (e as { locale?: unknown }).locale === 'string'
  )
}

export function isSourceUnavailableError(e: unknown): e is SourceUnavailableError {
  return (
    isI18nTranslatorError(e) &&
    e.code === 'SOURCE_UNAVAILABLE' &&
    typeof (e as { entityType?: unknown }).entityType === 'string' &&
    typeof (e as { entityId?: unknown }).entityId === 'string'
  )
}

export function isNoAdaptersConfiguredError(e: unknown): e is NoAdaptersConfiguredError {
  return isI18nTranslatorError(e) && e.code === 'NO_ADAPTERS_CONFIGURED'
}