///|
/// ═══ 功能组:error(类型化错误,T7)═══
/// PrismError:SDK 边界的类型化错误(LucentErrorKind 上翻)。
///
/// 背景(架构审计 P1-5):lux 已有类型化 LucentErrorKind,但 SDK
/// 边界全是 Result[_, String]——消费者的重试/熔断策略只能字符串
/// 匹配 provider_code。本组把类型化错误上翻到 SDK 边界,同时
/// **完整保留**既有 String 错误 API(兼容,不破坏公开 API)。

///|
/// PrismError — SDK 层类型化错误
///
/// kind 复用 IR 的 LucentErrorKind(RateLimit/Authentication/
/// ServerError/ContentFilter/InvalidRequest/Native),让重试与
/// 熔断策略按类型匹配而非字符串匹配。
pub struct PrismError {
  kind : @lux.LucentErrorKind
  message : String
  /// 出错的 provider(运行时解析后的规范名;未解析为 None)
  provider : String?
} derive(Eq, Debug)

///|
/// explicit: Eq::equal kept as a regular method (implicit promotion is deprecated, E0079)
pub extend PrismError with Eq::{equal}

///|
#deprecated("Use `!=` instead", skip_current_package=true)
#doc(hidden)
pub extend PrismError with Eq::{not_equal}

///|
#deprecated("Use `Debug::to_repr` instead", skip_current_package=true)
#doc(hidden)
pub extend PrismError with @moonbitlang/core/debug.Debug::{to_repr}

///|
pub fn PrismError::new(
  kind : @lux.LucentErrorKind,
  message : String,
  provider : String?,
) -> PrismError {
  { kind, message, provider, }
}

///|
/// 从字符串错误分类(尽力而为的启发式,provider=None)
///
/// 六函数契约固定返回 String(命名规则 §3.1),类型信息在该边界
/// 丢失;分类器按消息内容**保守**推断:
/// - 未命中任何模式 → Native("unclassified")(绝不误判为可重试)
/// - 宁可漏分类,不可错分类——错分类会导致错误的重试行为
///   (如把鉴权失败当限流重试)
pub fn PrismError::from_string(message : String) -> PrismError {
  PrismError::new(classify_message(message), message, None)
}

///|
/// 设置 provider 字段(builder)
pub fn PrismError::with_provider(
  self : PrismError,
  provider : String?,
) -> PrismError {
  { ..self, provider, }
}

///|
/// 是否可重试(限流与服务端错误)
pub fn PrismError::is_retryable(self : PrismError) -> Bool {
  match self.kind {
    RateLimit | ServerError => true
    _ => false
  }
}

///|
/// 错误消息文本(兼容 String 错误时代的展示)
pub fn PrismError::message(self : PrismError) -> String {
  self.message
}

///|
/// 保守分类:按优先级匹配消息模式
fn classify_message(message : String) -> @lux.LucentErrorKind {
  let m = message.to_lower()
  // 1. 限流(先于 server:429 与 5xx 是不同重试语义)
  if m.contains("rate limit") ||
    m.contains("rate_limit") ||
    m.contains("too many requests") ||
    m.contains("429") {
    RateLimit
    // 2. 鉴权
  } else if m.contains("unauthorized") ||
    m.contains("authentication") ||
    m.contains("api key") ||
    m.contains("api-key") ||
    m.contains("permission") ||
    m.contains("401") {
    Authentication
    // 3. 内容过滤(先于 invalid:两者处置不同)
  } else if m.contains("content filter") ||
    m.contains("content_filter") ||
    m.contains("safety") ||
    m.contains("moderation") {
    ContentFilter
    // 4. 请求非法(含协议/路由/解析错误)
  } else if m.contains("invalid") ||
    m.contains("malformed") ||
    m.contains("parse") ||
    m.contains("json") ||
    m.contains("missing") ||
    m.contains("unsupported") ||
    m.contains("unknown provider") ||
    m.contains("400") {
    InvalidRequest
    // 5. 服务端/传输错误
  } else if m.contains("server") ||
    m.contains("unavailable") ||
    m.contains("timeout") ||
    m.contains("network") ||
    m.contains("connection") ||
    m.contains("500") ||
    m.contains("502") ||
    m.contains("503") {
    ServerError
  } else {
    // 6. 未分类:不猜
    Native("unclassified")
  }
}