use serde::{Deserialize, Serialize};

/// Model modality. Stored as `"text"`, `"image"`, `"audio"`, or `"multimodal"`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum ModelModality {
    Text,
    Image,
    Audio,
    Multimodal,
}

impl std::fmt::Display for ModelModality {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ModelModality::Text => write!(f, "text"),
            ModelModality::Image => write!(f, "image"),
            ModelModality::Audio => write!(f, "audio"),
            ModelModality::Multimodal => write!(f, "multimodal"),
        }
    }
}

impl std::str::FromStr for ModelModality {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "text" => Ok(ModelModality::Text),
            "image" => Ok(ModelModality::Image),
            "audio" => Ok(ModelModality::Audio),
            "multimodal" => Ok(ModelModality::Multimodal),
            _ => Err("unknown model modality"),
        }
    }
}

/// Primary model capability. Stored as `"chat"`, `"completion"`, `"embedding"`,
/// or `"code"`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum ModelCapability {
    Chat,
    Completion,
    Embedding,
    Code,
}

impl std::fmt::Display for ModelCapability {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ModelCapability::Chat => write!(f, "chat"),
            ModelCapability::Completion => write!(f, "completion"),
            ModelCapability::Embedding => write!(f, "embedding"),
            ModelCapability::Code => write!(f, "code"),
        }
    }
}

impl std::str::FromStr for ModelCapability {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "chat" => Ok(ModelCapability::Chat),
            "completion" => Ok(ModelCapability::Completion),
            "embedding" => Ok(ModelCapability::Embedding),
            "code" => Ok(ModelCapability::Code),
            _ => Err("unknown model capability"),
        }
    }
}

/// Model or model-version availability status. Stored as `"active"` or
/// `"deprecated"`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum ModelStatus {
    Active,
    Deprecated,
}

impl std::fmt::Display for ModelStatus {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ModelStatus::Active => write!(f, "active"),
            ModelStatus::Deprecated => write!(f, "deprecated"),
        }
    }
}

impl std::str::FromStr for ModelStatus {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "active" => Ok(ModelStatus::Active),
            "deprecated" => Ok(ModelStatus::Deprecated),
            _ => Err("unknown model status"),
        }
    }
}

/// Capability type for per-version capability records. Stored as
/// `"function_call"`, `"tool_use"`, `"vision"`, or `"reasoning"`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum CapabilityType {
    FunctionCall,
    ToolUse,
    Vision,
    Reasoning,
}

impl std::fmt::Display for CapabilityType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            CapabilityType::FunctionCall => write!(f, "function_call"),
            CapabilityType::ToolUse => write!(f, "tool_use"),
            CapabilityType::Vision => write!(f, "vision"),
            CapabilityType::Reasoning => write!(f, "reasoning"),
        }
    }
}

impl std::str::FromStr for CapabilityType {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "function_call" => Ok(CapabilityType::FunctionCall),
            "tool_use" => Ok(CapabilityType::ToolUse),
            "vision" => Ok(CapabilityType::Vision),
            "reasoning" => Ok(CapabilityType::Reasoning),
            _ => Err("unknown capability type"),
        }
    }
}

/// Pricing currency. Stored as `"USD"` or `"CNY"`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum PricingCurrency {
    Usd,
    Cny,
}

impl std::fmt::Display for PricingCurrency {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            PricingCurrency::Usd => write!(f, "USD"),
            PricingCurrency::Cny => write!(f, "CNY"),
        }
    }
}

impl std::str::FromStr for PricingCurrency {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "USD" => Ok(PricingCurrency::Usd),
            "CNY" => Ok(PricingCurrency::Cny),
            _ => Err("unknown pricing currency"),
        }
    }
}

pub use model::Entity as Model;
pub use model_capability::Entity as ModelCapabilityRecord;
pub use model_parameter_profile::Entity as ModelParameterProfile;
pub use model_pricing::Entity as ModelPricing;
pub use model_provider::Entity as ModelProvider;
pub use model_version::Entity as ModelVersion;

pub mod model;
pub mod model_capability;
pub mod model_parameter_profile;
pub mod model_pricing;
pub mod model_provider;
pub mod model_version;
