//! L2 integration tests for [`FsPermissionStore`] against a real temp project.

use std::path::PathBuf;
use std::sync::Arc;

use domain::ids::{AgentId, ProjectId};
use domain::ports::{FileSystem, PermissionStore};
use domain::project::{Project, ProjectPath};
use domain::remote::RemoteRef;
use domain::{
    AgentPermissionOverride, PermissionSet, Posture, ProjectPermissions, PERMISSIONS_VERSION,
};
use infrastructure::{FsPermissionStore, LocalFileSystem};
use uuid::Uuid;

/// A unique scratch project directory under the OS temp dir, cleaned up on drop.
struct TempDir(PathBuf);

impl TempDir {
    fn new() -> Self {
        let p = std::env::temp_dir().join(format!("idea-l2-permissions-{}", Uuid::new_v4()));
        std::fs::create_dir_all(&p).unwrap();
        Self(p)
    }

    fn project_root(&self) -> String {
        self.0.to_string_lossy().into_owned()
    }
}

impl Drop for TempDir {
    fn drop(&mut self) {
        let _ = std::fs::remove_dir_all(&self.0);
    }
}

fn store() -> FsPermissionStore {
    let fs: Arc<dyn FileSystem> = Arc::new(LocalFileSystem::new());
    FsPermissionStore::new(fs)
}

fn project(tmp: &TempDir) -> Project {
    Project::new(
        ProjectId::new_random(),
        "permissions",
        ProjectPath::new(tmp.project_root()).unwrap(),
        RemoteRef::local(),
        1_700_000_000_000,
    )
    .unwrap()
}

#[tokio::test]
async fn missing_permissions_file_returns_default_document() {
    let tmp = TempDir::new();
    let project = project(&tmp);

    let loaded = store().load_permissions(&project).await.unwrap();

    assert_eq!(loaded, ProjectPermissions::default());
    assert_eq!(loaded.version, PERMISSIONS_VERSION);
}

#[tokio::test]
async fn save_then_load_roundtrips_project_defaults_and_agent_override() {
    let tmp = TempDir::new();
    let project = project(&tmp);
    let agent = AgentId::new_random();
    let doc = ProjectPermissions::new(
        Some(PermissionSet::new(vec![], Posture::Ask)),
        vec![AgentPermissionOverride::new(
            agent,
            PermissionSet::new(vec![], Posture::Deny),
        )],
    );

    let store = store();
    store.save_permissions(&project, &doc).await.unwrap();

    let loaded = store.load_permissions(&project).await.unwrap();
    assert_eq!(loaded, doc);
    assert_eq!(loaded.resolve_for(agent).unwrap().fallback(), Posture::Deny);

    let path = tmp.0.join(".ideai").join("permissions.json");
    assert!(path.exists(), "store writes under .ideai/permissions.json");
}
