use std::{collections::HashMap, sync::Arc};

use async_trait::async_trait;

use crate::{
    data::BaseData,
    storage::{
        visitor::Visitor,
        visitor_manager::{AddDataOptions, VisitorManager},
    },
};

pub struct MockVisitorManager {
    visitors: HashMap<String, Arc<Visitor>>,
}

#[async_trait]
impl VisitorManager for MockVisitorManager {
    // fn count(&self) -> usize {
    //     todo!()
    // }

    fn enumerate_visitor_codes(&self, _: impl FnMut(&String) -> bool) {
        todo!()
    }

    fn peek(&self, visitor_code: &str) -> Option<Arc<Visitor>> {
        self.visitors.get(visitor_code).map(|v| v.clone())
    }

    fn get(&self, visitor_code: &str) -> Option<Arc<Visitor>> {
        self.visitors.get(visitor_code).map(|v| {
            v.update_last_activity_time();
            v.clone()
        })
    }

    fn get_or_create(&self, _visitor_code: &str) -> Arc<Visitor> {
        todo!()
    }

    fn add_data(
        &self,
        _visitor_code: &str,
        _data: impl Iterator<Item = BaseData>,
        _options: AddDataOptions,
    ) -> Arc<Visitor> {
        todo!()
    }

    fn start_purging(&self, _: std::time::Duration) {
        todo!()
    }
}

impl MockVisitorManager {
    pub fn new() -> Self {
        Self {
            visitors: HashMap::new(),
        }
    }

    pub(crate) fn new_with_visitor(visitor_code: &str, visitor: Visitor) -> Self {
        let mut visitors = HashMap::new();
        visitors.insert(visitor_code.to_owned(), Arc::new(visitor));
        Self { visitors }
    }
}
