use std::collections::HashMap;
use std::sync::RwLock;

use async_trait::async_trait;

use crate::storage::StorageError;

use super::types::TaskSession;

/// 任务持久化接口
#[async_trait]
pub trait TaskRepository: Send + Sync + 'static {
    /// 保存任务会话
    async fn save_task_session(&self, session: &TaskSession) -> Result<(), StorageError>;

    /// 加载任务会话
    async fn load_task_session(&self, task_id: &str) -> Result<Option<TaskSession>, StorageError>;

    /// 删除任务会话
    async fn delete_task_session(&self, task_id: &str) -> Result<bool, StorageError>;

    /// 列出父会话的所有任务
    async fn list_tasks_for_session(
        &self,
        parent_session_id: &str,
    ) -> Result<Vec<TaskSession>, StorageError>;

    /// 列出父话题的所有任务
    async fn list_tasks_for_topic(
        &self,
        parent_topic_id: &str,
    ) -> Result<Vec<TaskSession>, StorageError>;

    /// 清理过期任务（超过指定小时）
    async fn cleanup_expired_tasks(&self, ttl_hours: u64) -> Result<usize, StorageError>;
}

/// 内存实现（用于测试）
pub struct InMemoryTaskRepository {
    sessions: RwLock<HashMap<String, TaskSession>>,
}

impl InMemoryTaskRepository {
    pub fn new() -> Self {
        Self {
            sessions: RwLock::new(HashMap::new()),
        }
    }
}

impl Default for InMemoryTaskRepository {
    fn default() -> Self {
        Self::new()
    }
}

#[async_trait]
impl TaskRepository for InMemoryTaskRepository {
    async fn save_task_session(&self, session: &TaskSession) -> Result<(), StorageError> {
        tracing::debug!(
            task_id = %session.id,
            session_id = %session.session_id,
            state = ?session.state,
            "Saving task session"
        );
        self.sessions
            .write()
            .unwrap()
            .insert(session.id.clone(), session.clone());
        tracing::debug!(
            task_id = %session.id,
            total_tasks = self.sessions.read().unwrap().len(),
            "Task session saved, current repository size"
        );
        Ok(())
    }

    async fn load_task_session(&self, task_id: &str) -> Result<Option<TaskSession>, StorageError> {
        let sessions = self.sessions.read().unwrap();
        let total = sessions.len();
        let keys: Vec<&str> = sessions.keys().map(|k| k.as_str()).collect();
        tracing::debug!(
            lookup_task_id = %task_id,
            total_tasks = total,
            all_keys = ?keys,
            "Looking up task session"
        );
        Ok(sessions.get(task_id).cloned())
    }

    async fn delete_task_session(&self, task_id: &str) -> Result<bool, StorageError> {
        Ok(self.sessions.write().unwrap().remove(task_id).is_some())
    }

    async fn list_tasks_for_session(
        &self,
        parent_session_id: &str,
    ) -> Result<Vec<TaskSession>, StorageError> {
        Ok(self
            .sessions
            .read()
            .unwrap()
            .values()
            .filter(|s| s.parent_session_id == parent_session_id)
            .cloned()
            .collect())
    }

    async fn list_tasks_for_topic(
        &self,
        parent_topic_id: &str,
    ) -> Result<Vec<TaskSession>, StorageError> {
        Ok(self
            .sessions
            .read()
            .unwrap()
            .values()
            .filter(|s| s.parent_topic_id.as_ref() == Some(&parent_topic_id.to_string()))
            .cloned()
            .collect())
    }

    async fn cleanup_expired_tasks(&self, ttl_hours: u64) -> Result<usize, StorageError> {
        let now = current_timestamp();
        let ttl_millis = ttl_hours * 3600 * 1000;
        let mut sessions = self.sessions.write().unwrap();
        let before = sessions.len();
        sessions.retain(|_, s| now - s.updated_at < ttl_millis as i64);
        Ok(before - sessions.len())
    }
}

fn current_timestamp() -> i64 {
    std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .expect("system clock before unix epoch")
        .as_millis() as i64
}