use std::path::Path;

use crate::backend::{VcsMetadata, WorkspaceInfo};
use crate::error::{Result, WorktreeError};

/// Active workspace handle with lifecycle state.
///
/// Wraps [`WorkspaceInfo`] (the backend's DTO) with an `is_active` flag managed
/// by [`crate::manager::WorktreeManager`]. Mutation methods live here, not on
/// the trait, because the backend is stateless with respect to activation.
#[derive(Clone, Debug)]
pub struct WorktreeHandle {
    pub info: WorkspaceInfo,
    pub is_active: bool,
}

impl WorktreeHandle {
    pub fn new(info: WorkspaceInfo) -> Self {
        Self {
            info,
            is_active: true,
        }
    }

    pub fn id(&self) -> &str {
        &self.info.id
    }

    pub fn agent_id(&self) -> &str {
        &self.info.agent_id
    }

    pub fn path(&self) -> &Path {
        &self.info.path
    }

    /// Branch (git) or workspace name (jj) — the VCS ref for this workspace.
    pub fn ref_name(&self) -> &str {
        match &self.info.vcs {
            VcsMetadata::Git { branch, .. } => branch,
            VcsMetadata::Jj { workspace_name, .. } => workspace_name,
        }
    }

    /// Stable identifier: change_id for jj, commit SHA for git.
    pub fn vcs_id(&self) -> &str {
        match &self.info.vcs {
            VcsMetadata::Jj { change_id, .. } => change_id,
            VcsMetadata::Git { commit_sha, .. } => commit_sha,
        }
    }

    pub fn deactivate(&mut self) {
        self.is_active = false;
    }

    pub fn can_modify(&self) -> Result<()> {
        if !self.is_active {
            return Err(WorktreeError::InvalidState(format!(
                "Workspace {} is no longer active",
                self.info.id
            )));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use std::path::PathBuf;

    use chrono::Utc;

    use super::*;
    use crate::backend::VcsMetadata;

    fn make_handle(agent_id: &str) -> WorktreeHandle {
        WorktreeHandle::new(WorkspaceInfo {
            id: "test-ws-001".to_string(),
            agent_id: agent_id.to_string(),
            path: PathBuf::from("/tmp/ws-001"),
            vcs: VcsMetadata::Git {
                branch: "agent/agent-001/test-ws-001".to_string(),
                commit_sha: "abc123".to_string(),
            },
            created_at: Utc::now(),
        })
    }

    #[test]
    fn handle_creation() {
        let h = make_handle("agent-001");
        assert_eq!(h.agent_id(), "agent-001");
        assert_eq!(h.id(), "test-ws-001");
        assert_eq!(h.ref_name(), "agent/agent-001/test-ws-001");
        assert!(h.is_active);
        assert!(h.can_modify().is_ok());
    }

    #[test]
    fn deactivation_blocks_modify() {
        let mut h = make_handle("agent-001");
        assert!(h.can_modify().is_ok());
        h.deactivate();
        assert!(!h.is_active);
        assert!(h.can_modify().is_err());
    }

    #[test]
    fn jj_handle_ref_name() {
        let h = WorktreeHandle::new(WorkspaceInfo {
            id: "ws-uuid".to_string(),
            agent_id: "agent-002".to_string(),
            path: PathBuf::from("/tmp/ws-uuid"),
            vcs: VcsMetadata::Jj {
                change_id: "yostqsxwmrkpkzqz".to_string(),
                workspace_name: "ws-uuid".to_string(),
            },
            created_at: Utc::now(),
        });
        assert_eq!(h.ref_name(), "ws-uuid");
        assert_eq!(h.vcs_id(), "yostqsxwmrkpkzqz");
    }
}
