use app_tauri_lib::dto::{
    ProjectSystemPermissionsDto, ResolvedAgentSystemPermissionsDto,
    UpdateProjectSystemPermissionsRequestDto,
};
use domain::{
    NetworkPolicy, ProjectSystemPermissions, ResolvedAgentSystemPermissions, RuntimeLock,
    RuntimeLockState, SystemPermissionControl, SystemPermissionControlMode, SystemPermissionSet,
};
use serde_json::json;

#[test]
fn project_system_permissions_dto_serializes_network_policy_contract() {
    let dto = ProjectSystemPermissionsDto(ProjectSystemPermissions::new(
        Some(SystemPermissionSet::new(Some(NetworkPolicy::Ask))),
        vec![],
    ));

    let value = serde_json::to_value(dto).unwrap();

    assert_eq!(
        value,
        json!({
            "version": 1,
            "projectDefault": {
                "network": "ask",
            },
        })
    );
}

#[test]
fn update_project_system_permissions_request_deserializes_allow_deny_ask() {
    let dto: UpdateProjectSystemPermissionsRequestDto = serde_json::from_value(json!({
        "projectId": "project",
        "permissions": {
            "network": "allow",
        },
    }))
    .unwrap();

    assert_eq!(
        dto.permissions.and_then(|permissions| permissions.network),
        Some(NetworkPolicy::Allow)
    );
}

#[test]
fn resolved_agent_system_permissions_dto_separates_wanted_control_from_runtime_control() {
    let dto = ResolvedAgentSystemPermissionsDto(ResolvedAgentSystemPermissions {
        wanted: Some(NetworkPolicy::Allow),
        effective: NetworkPolicy::Deny,
        runtime_lock: RuntimeLock {
            state: RuntimeLockState::Locked,
            source: Some("external-runtime".to_owned()),
            reason: Some("not inspectable".to_owned()),
        },
        control: SystemPermissionControl {
            mode: SystemPermissionControlMode::Editable,
            reason: None,
        },
        runtime_control: SystemPermissionControl {
            mode: SystemPermissionControlMode::ReadOnly,
            reason: Some("runtime not editable".to_owned()),
        },
    });

    let value = serde_json::to_value(dto).unwrap();

    assert_eq!(value["wanted"], "allow");
    assert_eq!(value["effective"], "deny");
    assert_eq!(value["runtimeLock"]["state"], "locked");
    assert_eq!(value["control"]["mode"], "editable");
    assert_eq!(value["runtimeControl"]["mode"], "readOnly");
}
