//! Supabase-specific backend implementation.
use crate::client::backend::{
    BackendError, BackendResult, BackendType, DatabaseBackend, HealthStatus, QueryLanguage,
    QueryResult, TranslatedQuery,
};
use crate::drivers::supabase::client::{HealthAwareSupabaseClient, SupabaseConnectionInfo};
use async_trait::async_trait;

pub struct SupabaseBackend {
    client: HealthAwareSupabaseClient,
}

impl SupabaseBackend {
    pub fn new(info: SupabaseConnectionInfo) -> BackendResult<Self> {
        let client = HealthAwareSupabaseClient::new(info).map_err(|err| {
            BackendError::Generic(format!("failed to build supabase client: {err}"))
        })?;
        Ok(Self { client })
    }

    pub fn from_env(url_key: &str, key_key: &str) -> BackendResult<Self> {
        let info = SupabaseConnectionInfo::from_env(url_key, key_key)
            .map_err(|err| BackendError::Generic(err.to_string()))?;
        Self::new(info)
    }
}

#[async_trait]
impl DatabaseBackend for SupabaseBackend {
    async fn execute_query(&self, query: TranslatedQuery) -> BackendResult<QueryResult> {
        if !matches!(query.language, QueryLanguage::Sql) {
            return Err(BackendError::Generic(
                "Supabase backend only supports SQL".to_string(),
            ));
        }

        let table = query.table.as_deref().unwrap_or("");
        let rows = self
            .client
            .execute(table, &query.sql)
            .await
            .map_err(|err| BackendError::Generic(err.to_string()))?;

        Ok(QueryResult::new(rows, Vec::new()))
    }

    async fn health_check(&self) -> BackendResult<HealthStatus> {
        if let Some(deadline) = self.client.is_offline() {
            Ok(HealthStatus::Offline(deadline))
        } else {
            Ok(HealthStatus::Healthy)
        }
    }

    fn backend_type(&self) -> BackendType {
        BackendType::Supabase
    }

    fn supports_sql(&self) -> bool {
        true
    }

    fn supports_cql(&self) -> bool {
        false
    }
}
