use crate::agent::{AgentRuntimeConfig, AgentStoredSettings, AgentTaskRoute, TaskProfile};
use crate::error::AppError;

pub fn resolve_runtime(
    settings: &AgentStoredSettings,
    task_profile: TaskProfile,
    model_override: Option<String>,
) -> Result<AgentRuntimeConfig, AppError> {
    let route = settings
        .task_defaults
        .get(&task_profile)
        .ok_or(AppError::TaskRouteMissing(task_profile))?;

    if !settings.remote.enabled {
        return Err(AppError::ProviderNotConfigured);
    }

    let api_key = settings.remote.api_key.trim().to_string();
    if api_key.is_empty() {
        return Err(AppError::RemoteApiKeyMissing);
    }

    Ok(AgentRuntimeConfig {
        base_url: settings.remote.base_url.clone(),
        model: resolve_model(settings, task_profile, route, model_override)?,
        api_key: Some(api_key),
    })
}

pub fn validate_settings(settings: &AgentStoredSettings) -> Result<(), AppError> {
    if settings.remote.base_url.trim().is_empty() {
        return Err(AppError::InvalidSettings(
            "remote base URL cannot be empty".to_string(),
        ));
    }

    if settings.default_remote_model.trim().is_empty() {
        return Err(AppError::InvalidSettings(
            "default remote model cannot be empty".to_string(),
        ));
    }

    for task in TaskProfile::all() {
        let route = settings
            .task_defaults
            .get(&task)
            .ok_or(AppError::TaskRouteMissing(task))?;
        let model = normalize_route_model(settings, task, route.clone())?.model;

        if model.trim().is_empty() {
            return Err(AppError::ModelMissing(task));
        }
    }

    Ok(())
}

pub fn normalize_routes(settings: &mut AgentStoredSettings) -> Result<(), AppError> {
    for task in TaskProfile::all() {
        let route = settings
            .task_defaults
            .get(&task)
            .cloned()
            .ok_or(AppError::TaskRouteMissing(task))?;
        let normalized = normalize_route_model(settings, task, route)?;
        settings.task_defaults.insert(task, normalized);
    }

    Ok(())
}

pub fn compute_remote_configured(settings: &AgentStoredSettings) -> bool {
    settings.remote.enabled
        && !settings.remote.base_url.trim().is_empty()
        && !settings.remote.api_key.trim().is_empty()
        && !settings.default_remote_model.trim().is_empty()
}

pub fn compute_overall_configured(settings: &AgentStoredSettings) -> bool {
    validate_settings(settings).is_ok() && compute_remote_configured(settings)
}

fn resolve_model(
    settings: &AgentStoredSettings,
    task_profile: TaskProfile,
    route: &AgentTaskRoute,
    model_override: Option<String>,
) -> Result<String, AppError> {
    if let Some(model) = model_override {
        let trimmed = model.trim();
        if trimmed.is_empty() {
            return Err(AppError::ModelMissing(task_profile));
        }
        return Ok(trimmed.to_string());
    }

    Ok(normalize_route_model(settings, task_profile, route.clone())?.model)
}

fn normalize_route_model(
    settings: &AgentStoredSettings,
    task_profile: TaskProfile,
    route: AgentTaskRoute,
) -> Result<AgentTaskRoute, AppError> {
    let trimmed = route.model.trim();

    if trimmed.is_empty() {
        if settings.default_remote_model.trim().is_empty() {
            return Err(AppError::ModelMissing(task_profile));
        }

        return Ok(AgentTaskRoute {
            model: settings.default_remote_model.clone(),
        });
    }

    Ok(AgentTaskRoute {
        model: trimmed.to_string(),
    })
}
