#![allow(dead_code)]
use futures::stream::TryStreamExt;
use mongodb::Collection;
use mongodb::{
    bson::{doc, oid::ObjectId},
    error::Error as MongoError,
};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthStatistic {
    #[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
    pub id: Option<ObjectId>,
    pub user_id: String,
    #[serde(rename = "type")]
    pub stat_type: String,
    pub value: f64,
    pub unit: String,
    pub notes: Option<String>,
    pub recorded_at: String,
}

#[derive(Clone)]
pub struct HealthStatisticsRepository {
    collection: Collection<HealthStatistic>,
}

impl HealthStatisticsRepository {
    pub fn new(db: &mongodb::Database) -> Self {
        Self {
            collection: db.collection("health_statistics"),
        }
    }

    pub async fn create(&self, stat: &HealthStatistic) -> Result<HealthStatistic, MongoError> {
        let result = self.collection.insert_one(stat, None).await?;
        let mut created = stat.clone();
        created.id = Some(result.inserted_id.as_object_id().unwrap());
        Ok(created)
    }

    pub async fn find_by_user(&self, user_id: &str) -> Result<Vec<HealthStatistic>, MongoError> {
        let filter = doc! { "user_id": user_id };
        let cursor = self.collection.find(filter, None).await?;
        cursor.try_collect().await
    }

    pub async fn find_by_id(&self, id: &ObjectId) -> Result<Option<HealthStatistic>, MongoError> {
        let filter = doc! { "_id": id };
        self.collection.find_one(filter, None).await
    }

    pub async fn update(
        &self,
        id: &ObjectId,
        stat: &HealthStatistic,
    ) -> Result<Option<HealthStatistic>, MongoError> {
        let filter = doc! { "_id": id };
        self.collection.replace_one(filter, stat, None).await?;
        Ok(Some(stat.clone()))
    }

    pub async fn delete(&self, id: &ObjectId) -> Result<bool, MongoError> {
        let filter = doc! { "_id": id };
        let result = self.collection.delete_one(filter, None).await?;
        Ok(result.deleted_count > 0)
    }
}
