use std::sync::Arc;

use axum::{
    extract::{Path, Query, Request, State},
    response::Json,
};
use serde::Deserialize;
use uuid::Uuid;

use crate::error::{auth, http, ControlCenterError, Result};
use crate::handlers::auth::ApiResponse;
use crate::middleware::RequestExt;
use crate::models::{CreateUserRequest, UpdateUserRequest, UserResponse};
use crate::AppState;

/// Create user endpoint (admin only)
pub async fn create_user(
    State(app_state): State<Arc<AppState>>,
    Json(create_request): Json<CreateUserRequest>,
    request: Request,
) -> Result<Json<ApiResponse<UserResponse>>> {
    let user_context = request.require_user_context()?;

    // Check if user has admin role
    if !user_context.is_admin() {
        return Err(ControlCenterError::Http(http::HttpError::BadRequest(
            "Admin role required to create users".to_string(),
        )));
    }

    let user = app_state.user_service.create_user(create_request).await?;

    Ok(Json(ApiResponse::success_with_message(
        user,
        "User created successfully".to_string(),
    )))
}

/// Get current user profile
pub async fn get_current_user(
    State(app_state): State<Arc<AppState>>,
    request: Request,
) -> Result<Json<ApiResponse<UserResponse>>> {
    let user_context = request.require_user_context()?;

    let user = app_state
        .user_service
        .get_user_response_by_id(user_context.user_id)
        .await?;

    Ok(Json(ApiResponse::success(user)))
}

/// Get user by ID (admin/operator only)
pub async fn get_user_by_id(
    State(app_state): State<Arc<AppState>>,
    Path(user_id): Path<Uuid>,
    request: Request,
) -> Result<Json<ApiResponse<UserResponse>>> {
    let user_context = request.require_user_context()?;

    // Check if user has permission to read user data
    if !user_context.has_permission("users:read") && user_context.user_id != user_id {
        return Err(ControlCenterError::Http(http::HttpError::BadRequest(
            "Permission required to read user data".to_string(),
        )));
    }

    let user = app_state
        .user_service
        .get_user_response_by_id(user_id)
        .await?;

    Ok(Json(ApiResponse::success(user)))
}

/// List users with pagination (admin/operator only)
pub async fn list_users(
    State(app_state): State<Arc<AppState>>,
    Query(params): Query<ListUsersParams>,
    request: Request,
) -> Result<Json<ApiResponse<ListUsersResponse>>> {
    let user_context = request.require_user_context()?;

    // Check if user has permission to read users
    if !user_context.has_permission("users:read") {
        return Err(ControlCenterError::Http(http::HttpError::BadRequest(
            "Permission required to read users".to_string(),
        )));
    }

    let users = app_state
        .user_service
        .list_users(params.limit, params.offset, params.active_only)
        .await?;

    let total_count = app_state
        .user_service
        .get_user_count(params.active_only)
        .await?;

    let response = ListUsersResponse {
        users,
        total_count,
        limit: params.limit,
        offset: params.offset.unwrap_or(0),
    };

    Ok(Json(ApiResponse::success(response)))
}

/// Update current user profile
pub async fn update_current_user(
    State(app_state): State<Arc<AppState>>,
    Json(mut update_request): Json<UpdateUserRequest>,
    request: Request,
) -> Result<Json<ApiResponse<UserResponse>>> {
    let user_context = request.require_user_context()?;

    // Users can only update certain fields of their own profile
    // Reset potentially dangerous fields
    update_request.is_active = None;
    update_request.is_verified = None;
    update_request.roles = None;

    let user = app_state
        .user_service
        .update_user(user_context.user_id, update_request)
        .await?;

    Ok(Json(ApiResponse::success_with_message(
        user,
        "Profile updated successfully".to_string(),
    )))
}

/// Update user by ID (admin only)
pub async fn update_user_by_id(
    State(app_state): State<Arc<AppState>>,
    Path(user_id): Path<Uuid>,
    Json(update_request): Json<UpdateUserRequest>,
    request: Request,
) -> Result<Json<ApiResponse<UserResponse>>> {
    let user_context = request.require_user_context()?;

    // Check if user has permission to update users
    if !user_context.has_permission("users:write") {
        return Err(ControlCenterError::Http(http::HttpError::BadRequest(
            "Permission required to update users".to_string(),
        )));
    }

    let user = app_state
        .user_service
        .update_user(user_id, update_request)
        .await?;

    Ok(Json(ApiResponse::success_with_message(
        user,
        "User updated successfully".to_string(),
    )))
}

/// Delete user by ID (admin only)
pub async fn delete_user(
    State(app_state): State<Arc<AppState>>,
    Path(user_id): Path<Uuid>,
    request: Request,
) -> Result<Json<ApiResponse<String>>> {
    let user_context = request.require_user_context()?;

    // Check if user has permission to delete users
    if !user_context.has_permission("users:delete") {
        return Err(ControlCenterError::Http(http::HttpError::BadRequest(
            "Permission required to delete users".to_string(),
        )));
    }

    // Prevent self-deletion
    if user_context.user_id == user_id {
        return Err(ControlCenterError::Http(http::bad_request(
            "Cannot delete your own account",
        )));
    }

    app_state.user_service.delete_user(user_id).await?;

    Ok(Json(ApiResponse::success(
        "User deleted successfully".to_string(),
    )))
}

/// Activate user (admin only)
pub async fn activate_user(
    State(app_state): State<Arc<AppState>>,
    Path(user_id): Path<Uuid>,
    request: Request,
) -> Result<Json<ApiResponse<UserResponse>>> {
    let user_context = request.require_user_context()?;

    // Check if user has permission to update users
    if !user_context.has_permission("users:write") {
        return Err(ControlCenterError::Http(http::HttpError::BadRequest(
            "Permission required to activate users".to_string(),
        )));
    }

    let user = app_state.user_service.activate_user(user_id).await?;

    Ok(Json(ApiResponse::success_with_message(
        user,
        "User activated successfully".to_string(),
    )))
}

/// Deactivate user (admin only)
pub async fn deactivate_user(
    State(app_state): State<Arc<AppState>>,
    Path(user_id): Path<Uuid>,
    request: Request,
) -> Result<Json<ApiResponse<UserResponse>>> {
    let user_context = request.require_user_context()?;

    // Check if user has permission to update users
    if !user_context.has_permission("users:write") {
        return Err(ControlCenterError::Http(http::HttpError::BadRequest(
            "Permission required to deactivate users".to_string(),
        )));
    }

    // Prevent self-deactivation
    if user_context.user_id == user_id {
        return Err(ControlCenterError::Http(http::bad_request(
            "Cannot deactivate your own account",
        )));
    }

    let user = app_state.user_service.deactivate_user(user_id).await?;

    Ok(Json(ApiResponse::success_with_message(
        user,
        "User deactivated successfully".to_string(),
    )))
}

/// Verify user (admin only)
pub async fn verify_user(
    State(app_state): State<Arc<AppState>>,
    Path(user_id): Path<Uuid>,
    request: Request,
) -> Result<Json<ApiResponse<UserResponse>>> {
    let user_context = request.require_user_context()?;

    // Check if user has permission to update users
    if !user_context.has_permission("users:write") {
        return Err(ControlCenterError::Http(http::HttpError::BadRequest(
            "Permission required to verify users".to_string(),
        )));
    }

    let user = app_state.user_service.verify_user(user_id).await?;

    Ok(Json(ApiResponse::success_with_message(
        user,
        "User verified successfully".to_string(),
    )))
}

/// Add role to user (admin only)
pub async fn add_user_role(
    State(app_state): State<Arc<AppState>>,
    Path((user_id, role_name)): Path<(Uuid, String)>,
    request: Request,
) -> Result<Json<ApiResponse<UserResponse>>> {
    let user_context = request.require_user_context()?;

    // Check if user has permission to update users
    if !user_context.has_permission("users:write") {
        return Err(ControlCenterError::Http(http::HttpError::BadRequest(
            "Permission required to modify user roles".to_string(),
        )));
    }

    // Verify role exists
    if app_state
        .role_service
        .find_by_name(&role_name)
        .await?
        .is_none()
    {
        return Err(ControlCenterError::Auth(auth::AuthError::RoleNotFound(
            role_name,
        )));
    }

    let user = app_state
        .user_service
        .add_role(user_id, role_name.clone())
        .await?;

    Ok(Json(ApiResponse::success_with_message(
        user,
        format!("Role '{}' added successfully", role_name),
    )))
}

/// Remove role from user (admin only)
pub async fn remove_user_role(
    State(app_state): State<Arc<AppState>>,
    Path((user_id, role_name)): Path<(Uuid, String)>,
    request: Request,
) -> Result<Json<ApiResponse<UserResponse>>> {
    let user_context = request.require_user_context()?;

    // Check if user has permission to update users
    if !user_context.has_permission("users:write") {
        return Err(ControlCenterError::Http(http::HttpError::BadRequest(
            "Permission required to modify user roles".to_string(),
        )));
    }

    let user = app_state
        .user_service
        .remove_role(user_id, role_name.clone())
        .await?;

    Ok(Json(ApiResponse::success_with_message(
        user,
        format!("Role '{}' removed successfully", role_name),
    )))
}

/// Query parameters for listing users
#[derive(Debug, Deserialize)]
pub struct ListUsersParams {
    pub limit: Option<usize>,
    pub offset: Option<usize>,
    pub active_only: Option<bool>,
}

/// Response for listing users
#[derive(Debug, serde::Serialize)]
pub struct ListUsersResponse {
    pub users: Vec<UserResponse>,
    pub total_count: i64,
    pub limit: Option<usize>,
    pub offset: usize,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_list_users_params_defaults() {
        let params = ListUsersParams {
            limit: None,
            offset: None,
            active_only: None,
        };

        assert!(params.limit.is_none());
        assert!(params.offset.is_none());
        assert!(params.active_only.is_none());
    }

    #[test]
    fn test_list_users_response_creation() {
        let response = ListUsersResponse {
            users: Vec::new(),
            total_count: 0,
            limit: Some(10),
            offset: 0,
        };

        assert_eq!(response.users.len(), 0);
        assert_eq!(response.total_count, 0);
        assert_eq!(response.limit, Some(10));
        assert_eq!(response.offset, 0);
    }
}
