///|
/// Lucent IR — 内容与消息反序列化(LucentContent / LucentMessage / LucentConversationItem)
///
/// 共享 helper 见 deserialize_helpers;基础类型见 deserialize_primitives。

///|
/// === LucentContent ===
pub fn LucentContent::from_json(jv : Json) -> Result[LucentContent, String] {
  match jv {
    Object(m) =>
      match m.get("type") {
        Some(String(tp)) =>
          match tp {
            "text" => {
              let text = match get_str(m, "text") {
                Ok(s) => s
                Err(e) => return Err(e)
              }
              let anns : Array[LucentAnnotation]? = match m.get("annotations") {
                Some(Array(items)) =>
                  match parse_annotation_arr(items) {
                    Ok(arr) => Some(arr)
                    Err(_) => None
                  }
                _ => None
              }
              Ok(Text(text, anns))
            }
            "tool_use" => {
              let tu = match m.get("tool_use") {
                Some(j) =>
                  match LucentToolUse::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing tool_use")
              }
              Ok(ToolUse(tu))
            }
            "tool_result" => {
              let tr = match m.get("tool_result") {
                Some(j) =>
                  match LucentToolResult::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing tool_result")
              }
              Ok(ToolResult(tr))
            }
            "thinking" => {
              let th = match m.get("thinking") {
                Some(j) =>
                  match LucentThinking::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing thinking")
              }
              Ok(Thinking(th))
            }
            "refusal" => {
              let text = match get_str(m, "refusal") {
                Ok(s) => s
                Err(e) => return Err(e)
              }
              Ok(Refusal(text))
            }
            "image" => {
              let mm = match m.get("image") {
                Some(j) =>
                  match LucentMultimedia::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing image")
              }
              Ok(Image(mm))
            }
            "audio" => {
              let mm = match m.get("audio") {
                Some(j) =>
                  match LucentMultimedia::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing audio")
              }
              Ok(Audio(mm))
            }
            "video" => {
              let mm = match m.get("video") {
                Some(j) =>
                  match LucentMultimedia::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing video")
              }
              Ok(Video(mm))
            }
            "file" => {
              let mm = match m.get("file") {
                Some(j) =>
                  match LucentMultimedia::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing file")
              }
              Ok(File(mm))
            }
            "native" => {
              let tag = match get_str(m, "native_tag") {
                Ok(s) => s
                Err(e) => return Err(e)
              }
              let payload : Json = match m.get("native_payload") {
                Some(j) => j
                None => Json::null()
              }
              Ok(Native(tag, payload))
            }
            _ => Err("unknown content type")
          }
        Some(_) => Err("expected string for type")
        None => Err("missing type in LucentContent")
      }
    _ => Err("expected object for LucentContent")
  }
}

///|
/// === LucentMessage ===
pub fn LucentMessage::from_json(jv : Json) -> Result[LucentMessage, String] {
  match jv {
    Object(m) => {
      let role = match m.get("role") {
        Some(r) =>
          match LucentRole::from_json(r) {
            Ok(v) => v
            Err(e) => return Err(e)
          }
        None => return Err("missing role")
      }
      let content = match get_arr_content(m, "content") {
        Ok(v) => v
        Err(e) => return Err(e)
      }
      let reasoning = match m.get("reasoning") {
        Some(r) =>
          match LucentThinking::from_json(r) {
            Ok(v) => Some(v)
            Err(e) => return Err(e)
          }
        None => None
      }
      Ok({ role, content, phase: get_str_opt(m, "phase"), reasoning, })
    }
    _ => Err("expected object for LucentMessage")
  }
}

///|
/// === LucentConversationItem ===
pub fn LucentConversationItem::from_json(
  jv : Json,
) -> Result[LucentConversationItem, String] {
  match jv {
    Object(m) =>
      match m.get("type") {
        Some(String(tp)) =>
          match tp {
            "message" => {
              let msg = match m.get("message") {
                Some(j) =>
                  match LucentMessage::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing message")
              }
              Ok(Message(msg))
            }
            "tool_call" => {
              let tu = match m.get("tool_call") {
                Some(j) =>
                  match LucentToolUse::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing tool_call")
              }
              Ok(ToolCall(tu))
            }
            "tool_result" => {
              let tr = match m.get("tool_result") {
                Some(j) =>
                  match LucentToolResult::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing tool_result")
              }
              Ok(ToolResult(tr))
            }
            "reasoning" => {
              let th = match m.get("reasoning") {
                Some(j) =>
                  match LucentThinking::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing reasoning")
              }
              Ok(Reasoning(th))
            }
            "agent_action" => {
              let aa = match m.get("agent_action") {
                Some(j) =>
                  match LucentAgentAction::from_json(j) {
                    Ok(v) => v
                    Err(e) => return Err(e)
                  }
                None => return Err("missing agent_action")
              }
              Ok(AgentAction(aa))
            }
            _ => Err("unknown conversation item type")
          }
        Some(_) => Err("expected string for type")
        None => Err("missing type in LucentConversationItem")
      }
    _ => Err("expected object for LucentConversationItem")
  }
}