///|
/// ═══ 功能组:registry+match(注册与路由)═══
/// 本文件:注册表定义(ProviderRegistration + providers_cache + build_providers)。
/// 匹配逻辑见 match.mbt。
///
/// 依赖声明见 `moon.pkg`(MoonBit 不允许在 .mbt 内联 import)。

///|
/// 单个 Provider 注册条目
///
/// 身份字段(name / aliases / model_pattern / capability)与 `schema` 全部
/// 来自 `src/provider//meta.mbt`,本类型只负责把元数据与六个 codec
/// 函数绑在一起。新增 provider 时不要在 build_providers 里重复元数据字面量。
pub struct ProviderRegistration {
  /// 主名称(如 "openai" "messages")
  name : String
  /// 别名(如 "chat"、"google"、"claude-messages")
  aliases : Array[String]
  /// 能力声明
  capability : @lux.ProviderCapability
  /// model pattern(从 capability 提取,用于文本通配符匹配)
  model_pattern : String
  /// 该 provider 的字段约束 schema(来自 meta,供校验/schema facade 使用)
  schema : @meta.ProviderSchema
  /// 请求解码:provider JSON → LucentRequest(带诊断)
  request_decode : (String) -> Result[
    @lux.ConversionResult[@lux.LucentRequest],
    String,
  ]
  /// 请求编码:LucentRequest → provider JSON(带诊断)
  request_encode : (@lux.LucentRequest) -> Result[
    @lux.ConversionResult[String],
    String,
  ]
  /// 响应解码:provider JSON → LucentResponse(带诊断)
  response_decode : (String) -> Result[
    @lux.ConversionResult[@lux.LucentResponse],
    String,
  ]
  /// 响应编码:LucentResponse → provider JSON(带诊断)
  response_encode : (@lux.LucentResponse) -> Result[
    @lux.ConversionResult[String],
    String,
  ]
  /// 流式解码:SSE 文本 → StreamEvent 数组(带诊断)
  events_decode : (String) -> Result[
    @lux.ConversionResult[Array[@lux.LucentStreamEvent]],
    String,
  ]
  /// 流式编码:StreamEvent 数组 → SSE 文本(带诊断)
  events_encode : (Array[@lux.LucentStreamEvent]) -> Result[
    @lux.ConversionResult[String],
    String,
  ]
  /// 流式编码(ctx 感知,T5 增量转换用):逐帧转换时跨帧复用首帧
  /// 会话元信息(openai/responses 需要;messages/gemini 无状态,忽略 ctx)
  events_encode_with_ctx : (
    Array[@lux.LucentStreamEvent],
    @lux.LucentConversationMeta?,
  ) -> Result[@lux.ConversionResult[String], String]
  /// 部署态端点基址(Extension:可选,SDK 不发起 HTTP,仅供宿主路由读取)
  base_url : String?
  /// 认证头名(Extension:可选,如 "Authorization" / "x-api-key")
  auth_header : String?
  /// API 版本(Extension:可选,如 Azure "2024-10-21")
  api_version : String?
}

///|
pub fn ProviderRegistration::new(
  name : String,
  aliases : Array[String],
  capability : @lux.ProviderCapability,
  model_pattern : String,
  schema : @meta.ProviderSchema,
  request_decode : (String) -> Result[
    @lux.ConversionResult[@lux.LucentRequest],
    String,
  ],
  request_encode : (@lux.LucentRequest) -> Result[
    @lux.ConversionResult[String],
    String,
  ],
  response_decode : (String) -> Result[
    @lux.ConversionResult[@lux.LucentResponse],
    String,
  ],
  response_encode : (@lux.LucentResponse) -> Result[
    @lux.ConversionResult[String],
    String,
  ],
  events_decode : (String) -> Result[
    @lux.ConversionResult[Array[@lux.LucentStreamEvent]],
    String,
  ],
  events_encode : (Array[@lux.LucentStreamEvent]) -> Result[
    @lux.ConversionResult[String],
    String,
  ],
  events_encode_with_ctx : (
    Array[@lux.LucentStreamEvent],
    @lux.LucentConversationMeta?,
  ) -> Result[@lux.ConversionResult[String], String],
  base_url : String?,
  auth_header : String?,
  api_version : String?,
) -> ProviderRegistration {
  {
    name,
    aliases,
    capability,
    model_pattern,
    schema,
    request_decode,
    request_encode,
    response_decode,
    response_encode,
    events_decode,
    events_encode,
    events_encode_with_ctx,
    base_url,
    auth_header,
    api_version,
  }
}

///|
/// 从 provider 自有元数据构造注册项 —— registry 不再重复元数据字段。
pub fn ProviderRegistration::from_metadata(
  metadata : @meta.ProviderMeta,
  request_decode : (String) -> Result[
    @lux.ConversionResult[@lux.LucentRequest],
    String,
  ],
  request_encode : (@lux.LucentRequest) -> Result[
    @lux.ConversionResult[String],
    String,
  ],
  response_decode : (String) -> Result[
    @lux.ConversionResult[@lux.LucentResponse],
    String,
  ],
  response_encode : (@lux.LucentResponse) -> Result[
    @lux.ConversionResult[String],
    String,
  ],
  events_decode : (String) -> Result[
    @lux.ConversionResult[Array[@lux.LucentStreamEvent]],
    String,
  ],
  events_encode : (Array[@lux.LucentStreamEvent]) -> Result[
    @lux.ConversionResult[String],
    String,
  ],
  events_encode_with_ctx : (
    Array[@lux.LucentStreamEvent],
    @lux.LucentConversationMeta?,
  ) -> Result[@lux.ConversionResult[String], String],
  base_url : String?,
  auth_header : String?,
  api_version : String?,
) -> ProviderRegistration {
  ProviderRegistration::new(
    metadata.name(),
    metadata.aliases(),
    metadata.capability(),
    metadata.model_pattern(),
    metadata.schema(),
    request_decode,
    request_encode,
    response_decode,
    response_encode,
    events_decode,
    events_encode,
    events_encode_with_ctx,
    base_url,
    auth_header,
    api_version,
  )
}

///|
/// RegistrationOverrides — 薄注册覆盖项(T6,derive 工厂用)
///
/// 全部可选:None 表示继承基座值。codecs/capability/schema 不可覆盖
/// (协议能力属于基座 adapter;部署态只改身份与端点)。
pub struct RegistrationOverrides {
  name : String?
  aliases : Array[String]?
  model_pattern : String?
  base_url : String?
  auth_header : String?
  api_version : String?
}

///|
pub fn RegistrationOverrides::default() -> RegistrationOverrides {
  {
    name: None,
    aliases: None,
    model_pattern: None,
    base_url: None,
    auth_header: None,
    api_version: None,
  }
}

///|
/// 可选覆盖:Some 优先,否则继承基座值(with_overrides 共用)
fn[T] override_or(override_val : T?, base_val : T?) -> T? {
  match override_val {
    Some(v) => Some(v)
    None => base_val
  }
}

///|
/// 薄注册工厂:复用基座 adapter + 覆盖部署态元数据(azure/vllm 场景)
///
/// 六个 codec 函数与 capability/schema 原样继承(协议行为不变),
/// 只替换身份与端点字段——中间件为同一协议配多个部署端点时不重写
/// 转换逻辑。覆盖 name 时建议同步覆盖 model_pattern/aliases 避免与
/// 基座匹配冲突(静态表精确匹配优先,动态项不会遮蔽静态项)。
pub fn ProviderRegistration::with_overrides(
  self : ProviderRegistration,
  overrides : RegistrationOverrides,
) -> ProviderRegistration {
  {
    name: overrides.name.unwrap_or(self.name),
    aliases: match overrides.aliases {
      Some(a) => a
      None => self.aliases
    },
    capability: self.capability,
    model_pattern: overrides.model_pattern.unwrap_or(self.model_pattern),
    schema: self.schema,
    request_decode: self.request_decode,
    request_encode: self.request_encode,
    response_decode: self.response_decode,
    response_encode: self.response_encode,
    events_decode: self.events_decode,
    events_encode: self.events_encode,
    events_encode_with_ctx: self.events_encode_with_ctx,
    base_url: override_or(overrides.base_url, self.base_url),
    auth_header: override_or(overrides.auth_header, self.auth_header),
    api_version: override_or(overrides.api_version, self.api_version),
  }
}

///|
/// 所有已注册的 Provider(静态表 + 动态表,动态在后)
///
/// 新增 Provider 只需在 `build_providers` 中追加,或运行时
/// `register_provider`。注意:条目顺序影响匹配优先级(精确匹配
/// 优先于正则匹配;静态表整体优先于动态表)。
///
/// 每次调用返回独立数组,调用方可安全修改;内部匹配路径直接读
/// `providers_cache` / `dynamic_providers` 避免重复构造。
pub fn all_providers() -> Array[ProviderRegistration] {
  let result = providers_cache.copy()
  for reg in dynamic_providers {
    result.push(reg)
  }
  result
}

///|
/// 动态注册表 — 运行时 register_provider 追加(T6)
///
/// 与静态表分离:静态表是编译期启用集合(默认路径,行为不变),
/// 动态表承载中间件部署态配置(自定义端点/别名)。匹配时静态表
/// 优先,动态表兜底——默认路径零影响。
let dynamic_providers : Array[ProviderRegistration] = []

///|
/// 注册单个 Provider(运行时显式动态注册)
///
/// 用于中间件部署态:复用已有 adapter + 覆盖 model_pattern/endpoint
/// (配合 ProviderRegistration::derive 薄注册工厂)。
/// 幂等:同名主名称重复注册会替换旧动态项。
/// 注意:动态项不会遮蔽静态表的精确/别名匹配(静态优先)。
pub fn register_provider(reg : ProviderRegistration) -> Unit {
  let mut i = 0
  while i < dynamic_providers.length() {
    if dynamic_providers[i].name == reg.name {
      dynamic_providers[i] = reg
      return
    }
    i = i + 1
  }
  dynamic_providers.push(reg)
}

///|
/// 注销动态注册的 Provider(按主名称)
///
/// 静态表项不受影响(尝试注销静态名返回 false)。
/// 返回是否实际移除了动态项。
pub fn unregister_provider(name : String) -> Bool {
  let kept : Array[ProviderRegistration] = []
  let mut found = false
  for reg in dynamic_providers {
    if reg.name == name {
      found = true
    } else {
      kept.push(reg)
    }
  }
  if found {
    // 顶层 let 不可整体赋值:原地清空后重填(数组是引用类型)
    while dynamic_providers.length() > 0 {
      let _ = dynamic_providers.pop()
    }
    for reg in kept {
      dynamic_providers.push(reg)
    }
  }
  found
}

///|
/// 注册表缓存 — 构造一次复用
///
/// `build_providers` 会为每个条目调用 `capability()`,其中包含数组分配;
/// 匹配函数(`match_provider_name` / `match_by_model` / `list_provider_names`)
/// 属于每次 SDK 调用都会经过的热路径,故在模块初始化时构造一次。
/// 仅供只读使用。
let providers_cache : Array[ProviderRegistration] = build_providers()

///|
/// 注册表构造 — provider 静态启用集合的唯一清单
///
/// 顺序是匹配优先级的一部分:`responses` 与 `openai` 的 model_pattern 同为
/// `gpt-*,o*`,`match_by_model` 采用「严格大于」更新最优项,因此 gpt-* 模型
/// 会稳定命中排在前面的 `responses`。调整顺序前请先看 match.mbt 与相关测试。
fn build_providers() -> Array[ProviderRegistration] {
  [
    // OpenAI Responses
    ProviderRegistration::from_metadata(
      @responses.metadata(),
      @responses.responses_to_lux_request,
      @responses.lux_request_to_responses,
      @responses.responses_to_lux_response,
      @responses.lux_response_to_responses,
      @responses.responses_sse_to_events,
      @responses.lux_events_to_responses_sse,
      @responses.lux_events_to_responses_sse_with_ctx,
      None,
      None,
      None,
    ),
    // OpenAI Chat Completions
    ProviderRegistration::from_metadata(
      @openai.metadata(),
      @openai.openai_to_lux_request,
      @openai.lux_request_to_openai,
      @openai.openai_to_lux_response,
      @openai.lux_response_to_openai,
      @openai.openai_sse_to_events,
      @openai.lux_events_to_openai_sse,
      @openai.lux_events_to_openai_sse_with_ctx,
      None,
      None,
      None,
    ),
    // Anthropic Messages
    ProviderRegistration::from_metadata(
      @messages.metadata(),
      @messages.messages_to_lux_request,
      @messages.lux_request_to_messages,
      @messages.messages_to_lux_response,
      @messages.lux_response_to_messages,
      @messages.messages_sse_to_events,
      @messages.lux_events_to_messages_sse,
      // messages 编码无跨帧状态,忽略 ctx
      fn(
        events : Array[@lux.LucentStreamEvent],
        _ctx : @lux.LucentConversationMeta?,
      ) -> Result[@lux.ConversionResult[String], String] {
        @messages.lux_events_to_messages_sse(events)
      },
      None,
      None,
      None,
    ),
    // Google Gemini(REST API)
    ProviderRegistration::from_metadata(
      @gemini.metadata(),
      @gemini.gemini_to_lux_request,
      @gemini.lux_request_to_gemini,
      @gemini.gemini_to_lux_response,
      @gemini.lux_response_to_gemini,
      @gemini.gemini_sse_to_events,
      @gemini.lux_events_to_gemini_sse,
      // gemini 编码无跨帧状态,忽略 ctx
      fn(
        events : Array[@lux.LucentStreamEvent],
        _ctx : @lux.LucentConversationMeta?,
      ) -> Result[@lux.ConversionResult[String], String] {
        @gemini.lux_events_to_gemini_sse(events)
      },
      None,
      None,
      None,
    ),
  ]
}