//! `vlm_client` — optional Tier 3 NanoLLM/VILA Visual-Language-Model client.
//!
//! Default impl (`feature = "vlm"` OFF) returns `VlmAssessment::disabled()`.
//! Real IPC path lands in:
//! - AZ-672 `vlm_client_provider_trait`
//! - AZ-673 `vlm_client_nanollm_ipc`
//! - AZ-674 `vlm_client_schema_and_model_version`

use async_trait::async_trait;

use shared::contracts::VlmProvider;
use shared::error::Result;
use shared::health::ComponentHealth;
use shared::models::vlm::VlmAssessment;

const NAME: &str = "vlm_client";

#[derive(Debug, Clone, Default)]
pub struct VlmClient {
    enabled: bool,
}

impl VlmClient {
    /// Construct the no-op `VlmClient`. Returns `VlmAssessment::disabled()`
    /// from every `assess()` call.
    pub fn with_default() -> Self {
        Self { enabled: false }
    }

    #[cfg(feature = "vlm")]
    pub fn enabled() -> Self {
        Self { enabled: true }
    }

    pub fn health(&self) -> ComponentHealth {
        if self.enabled {
            ComponentHealth::green(NAME)
        } else {
            ComponentHealth::disabled(NAME)
        }
    }
}

#[async_trait]
impl VlmProvider for VlmClient {
    async fn assess(&self, _roi: Vec<u8>, _prompt: String) -> Result<VlmAssessment> {
        // Disabled path always returns the documented no-op assessment.
        // The real path lands in AZ-673.
        Ok(VlmAssessment::disabled())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn default_impl_returns_disabled_assessment() {
        // Arrange
        let c = VlmClient::with_default();

        // Act
        let result = c
            .assess(Vec::new(), String::new())
            .await
            .expect("disabled path is infallible");

        // Assert
        assert_eq!(result.status, shared::models::vlm::VlmStatus::Disabled);
        assert_eq!(result.label, shared::models::vlm::VlmLabel::Inconclusive);
    }
}
