use db::models::ai::{AiFeatureCost, AiPlan};
use serde::{Deserialize, Serialize};

/// Model aliases that may be resolved by the AI gateway. Only two real models
/// are supported by the platform.
pub const ASKASH_FAST: &str = "askash-fast";
pub const ASKASH_MAIN: &str = "askash-main";

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ModelTier {
    Fast,
    Main,
}

impl ModelTier {
    pub fn alias(&self) -> &'static str {
        match self {
            ModelTier::Fast => ASKASH_FAST,
            ModelTier::Main => ASKASH_MAIN,
        }
    }
}

impl std::str::FromStr for ModelTier {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "askash-fast" | "fast" => Ok(ModelTier::Fast),
            "askash-main" | "main" => Ok(ModelTier::Main),
            _ => Err(format!("unknown model tier: {}", s)),
        }
    }
}

/// Pick the right model for a feature considering user preference and plan.
/// Falls back to the feature's default model if the requested one is not
/// allowed by the plan.
pub fn resolve_model(
    feature: &AiFeatureCost,
    plan: &AiPlan,
    requested: Option<&str>,
) -> Result<String, super::plans::PlanError> {
    let preferred = requested
        .and_then(|m| m.parse::<ModelTier>().ok())
        .map(|t| t.alias().to_string())
        .unwrap_or_else(|| feature.default_model.clone());

    if super::plans::is_model_allowed(plan, &preferred) {
        Ok(preferred)
    } else if super::plans::is_model_allowed(plan, ASKASH_FAST) {
        Ok(ASKASH_FAST.to_string())
    } else {
        Err(super::plans::PlanError::ModelNotAllowed {
            model: preferred,
        })
    }
}

/// Map a feature code to a suggested model tier for cases where the caller
/// wants to force higher quality (e.g., long-form generation).
#[allow(dead_code)]
pub fn preferred_tier_for_feature(feature_code: &str) -> ModelTier {
    match feature_code {
        "jd_generate"
        | "jd_improve"
        | "cover_letter_generate"
        | "auto_apply_execute"
        | "admin_support_reply" => ModelTier::Main,
        _ => ModelTier::Fast,
    }
}

/// Convenience resolver that selects the best model alias for a feature,
/// preferring Main for complex features unless explicitly overridden.
#[allow(dead_code)]
pub fn resolve_best_model(
    feature: &AiFeatureCost,
    plan: &AiPlan,
    force_main: bool,
) -> Result<String, super::plans::PlanError> {
    let requested = if force_main {
        Some(ASKASH_MAIN)
    } else {
        Some(preferred_tier_for_feature(&feature.feature_code).alias())
    };
    resolve_model(feature, plan, requested)
}
