//! LLM types — `Message`, `Role`, `ToolCall`, `ModelProvider`, and related data structures.
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;

/// The role of a message participant in an LLM conversation.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum Role {
    System,
    User,
    Assistant,
    Tool,
}

/// A single message in an LLM conversation, including optional tool call attachments.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Message {
    pub role: Role,
    pub content: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub tool_calls: Option<Vec<ToolCall>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub tool_call_id: Option<String>,
}

/// A tool invocation requested by the LLM, containing the call ID and function details.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ToolCall {
    pub id: Option<String>,
    pub function: FunctionCall,
    #[serde(rename = "type")]
    pub kind: String,
}

/// The function name and JSON-encoded arguments for a tool call.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FunctionCall {
    pub name: String,
    pub arguments: String,
}

/// A tool definition passed to the LLM describing an available function and its schema.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ToolDefinition {
    #[serde(rename = "type")]
    pub kind: String,
    pub function: ToolFunctionDefinition,
}

/// The name, description, and JSON schema for a single tool function.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ToolFunctionDefinition {
    pub name: String,
    pub description: String,
    pub parameters: serde_json::Value,
}

/// The response from an LLM completion request, containing text and/or tool calls.
#[derive(Debug, Serialize, Deserialize)]
pub struct CompletionResponse {
    pub content: Option<String>,
    pub tool_calls: Option<Vec<ToolCall>>,
    /// Claude Code session ID for conversation resumption.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub session_id: Option<String>,
}

/// Trait for LLM backends; implementations drive chat completions with optional tool use.
#[async_trait]
#[allow(dead_code)]
pub trait ModelProvider: Send + Sync {
    async fn chat(
        &self,
        model: &str,
        messages: &[Message],
        tools: &[ToolDefinition],
    ) -> Result<CompletionResponse, String>;
}
