use std::sync::Arc;

use crate::client::TetrixClient;
use crate::errors::TetrixError;
use crate::types::*;

impl TetrixClient {
    // --- Organizations ---

    pub async fn create_org(
        self: &Arc<Self>,
        req: &CreateOrgRequest,
    ) -> Result<CreateOrgResponse, TetrixError> {
        self.request("CREATE_ORG", req).await
    }

    pub async fn get_org(
        self: &Arc<Self>,
        org_id: &str,
    ) -> Result<GetOrgResponse, TetrixError> {
        self.request("GET_ORG", &GetOrgRequest {
            org_id: org_id.to_string(),
        }).await
    }

    pub async fn update_org(
        self: &Arc<Self>,
        req: &UpdateOrgRequest,
    ) -> Result<UpdateOrgResponse, TetrixError> {
        self.request("UPDATE_ORG", req).await
    }

    pub async fn delete_org(self: &Arc<Self>, org_id: &str) -> Result<(), TetrixError> {
        let _: DeleteOrgResponse = self
            .request("DELETE_ORG", &DeleteOrgRequest {
                org_id: org_id.to_string(),
            })
            .await?;
        Ok(())
    }

    pub async fn list_orgs(self: &Arc<Self>) -> Result<ListOrgsResponse, TetrixError> {
        self.request("LIST_ORGS", &ListOrgsRequest {}).await
    }

    // --- Users ---

    pub async fn create_user(
        self: &Arc<Self>,
        req: &CreateUserRequest,
    ) -> Result<CreateUserResponse, TetrixError> {
        self.request("CREATE_USER", req).await
    }

    pub async fn get_user(
        self: &Arc<Self>,
        user_id: &str,
    ) -> Result<GetUserResponse, TetrixError> {
        self.request("GET_USER", &GetUserRequest {
            user_id: user_id.to_string(),
        }).await
    }

    pub async fn update_user(
        self: &Arc<Self>,
        req: &UpdateUserRequest,
    ) -> Result<UpdateUserResponse, TetrixError> {
        self.request("UPDATE_USER", req).await
    }

    pub async fn delete_user(self: &Arc<Self>, user_id: &str) -> Result<(), TetrixError> {
        let _: DeleteUserResponse = self
            .request("DELETE_USER", &DeleteUserRequest {
                user_id: user_id.to_string(),
            })
            .await?;
        Ok(())
    }

    pub async fn list_users(
        self: &Arc<Self>,
        org_id: Option<&str>,
    ) -> Result<ListUsersResponse, TetrixError> {
        self.request("LIST_USERS", &ListUsersRequest {
            org_id: org_id.map(|s| s.to_string()),
        }).await
    }

    // --- Teams ---

    pub async fn create_team(
        self: &Arc<Self>,
        req: &CreateTeamRequest,
    ) -> Result<CreateTeamResponse, TetrixError> {
        self.request("CREATE_TEAM", req).await
    }

    pub async fn get_team(
        self: &Arc<Self>,
        team_id: &str,
    ) -> Result<GetTeamResponse, TetrixError> {
        self.request("GET_TEAM", &GetTeamRequest {
            team_id: team_id.to_string(),
        }).await
    }

    pub async fn update_team(
        self: &Arc<Self>,
        req: &UpdateTeamRequest,
    ) -> Result<UpdateTeamResponse, TetrixError> {
        self.request("UPDATE_TEAM", req).await
    }

    pub async fn delete_team(self: &Arc<Self>, team_id: &str) -> Result<(), TetrixError> {
        let _: DeleteTeamResponse = self
            .request("DELETE_TEAM", &DeleteTeamRequest {
                team_id: team_id.to_string(),
            })
            .await?;
        Ok(())
    }

    pub async fn list_teams(
        self: &Arc<Self>,
        org_id: Option<&str>,
    ) -> Result<ListTeamsResponse, TetrixError> {
        self.request("LIST_TEAMS", &ListTeamsRequest {
            org_id: org_id.map(|s| s.to_string()),
        }).await
    }

    // --- Team Members ---

    pub async fn add_team_member(
        self: &Arc<Self>,
        req: &AddTeamMemberRequest,
    ) -> Result<AddTeamMemberResponse, TetrixError> {
        self.request("ADD_TEAM_MEMBER", req).await
    }

    pub async fn remove_team_member(
        self: &Arc<Self>,
        team_id: &str,
        user_id: &str,
    ) -> Result<(), TetrixError> {
        let _: RemoveTeamMemberResponse = self
            .request("REMOVE_TEAM_MEMBER", &RemoveTeamMemberRequest {
                team_id: team_id.to_string(),
                user_id: user_id.to_string(),
            })
            .await?;
        Ok(())
    }

    pub async fn list_team_members(
        self: &Arc<Self>,
        team_id: &str,
    ) -> Result<ListTeamMembersResponse, TetrixError> {
        self.request("LIST_TEAM_MEMBERS", &ListTeamMembersRequest {
            team_id: team_id.to_string(),
        }).await
    }

    // --- Entity Permissions ---

    pub async fn grant_permission(
        self: &Arc<Self>,
        req: &GrantPermissionRequest,
    ) -> Result<GrantPermissionResponse, TetrixError> {
        self.request("GRANT_PERMISSION", req).await
    }

    pub async fn revoke_permission(
        self: &Arc<Self>,
        req: &RevokePermissionRequest,
    ) -> Result<(), TetrixError> {
        let _: RevokePermissionResponse = self.request("REVOKE_PERMISSION", req).await?;
        Ok(())
    }

    pub async fn list_permissions(
        self: &Arc<Self>,
        entity_id: &str,
    ) -> Result<ListPermissionsResponse, TetrixError> {
        self.request("LIST_PERMISSIONS", &ListPermissionsRequest {
            entity_id: entity_id.to_string(),
        }).await
    }
}
