use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;

/// 所有数据库实体的公共字段
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BaseFields {
    pub id: Uuid,
    pub tenant_id: Uuid,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub created_by: Uuid,
    pub updated_by: Uuid,
    pub deleted_at: Option<DateTime<Utc>>,
    pub version: i32,
}

/// 分页请求
#[derive(Debug, Deserialize, utoipa::IntoParams)]
pub struct Pagination {
    pub page: Option<u64>,
    pub page_size: Option<u64>,
}

impl Pagination {
    pub fn offset(&self) -> u64 {
        (self.page.unwrap_or(1).saturating_sub(1)) * self.limit()
    }

    pub fn limit(&self) -> u64 {
        self.page_size.unwrap_or(20).min(100)
    }
}

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

    #[test]
    fn pagination_defaults() {
        let p = Pagination {
            page: None,
            page_size: None,
        };
        assert_eq!(p.limit(), 20);
        assert_eq!(p.offset(), 0);
    }

    #[test]
    fn pagination_custom_values() {
        let p = Pagination {
            page: Some(3),
            page_size: Some(10),
        };
        assert_eq!(p.limit(), 10);
        assert_eq!(p.offset(), 20); // (3-1) * 10
    }

    #[test]
    fn pagination_max_cap() {
        let p = Pagination {
            page: Some(1),
            page_size: Some(200),
        };
        assert_eq!(p.limit(), 100); // capped at 100
    }

    #[test]
    fn pagination_page_zero_treated_as_first() {
        // page 0 -> saturating_sub wraps to 0 -> offset = 0
        let p = Pagination {
            page: Some(0),
            page_size: Some(10),
        };
        assert_eq!(p.offset(), 0);
    }

    #[test]
    fn pagination_page_one() {
        let p = Pagination {
            page: Some(1),
            page_size: Some(50),
        };
        assert_eq!(p.offset(), 0);
    }

    #[test]
    fn paginated_response_total_pages() {
        let resp = PaginatedResponse {
            data: vec![1, 2, 3],
            total: 25,
            page: 1,
            page_size: 10,
            total_pages: 3,
        };
        assert_eq!(resp.data.len(), 3);
        assert_eq!(resp.total, 25);
        assert_eq!(resp.total_pages, 3);
    }

    #[test]
    fn api_response_ok() {
        let resp = ApiResponse::ok(42);
        assert!(resp.success);
        assert_eq!(resp.data, Some(42));
        assert!(resp.message.is_none());
    }

    #[test]
    fn tenant_context_fields() {
        let ctx = TenantContext {
            tenant_id: Uuid::now_v7(),
            user_id: Uuid::now_v7(),
            roles: vec!["admin".to_string()],
            permissions: vec!["user.read".to_string()],
            department_ids: vec![],
            permission_data_scopes: HashMap::new(),
        };
        assert_eq!(ctx.roles.len(), 1);
        assert_eq!(ctx.permissions.len(), 1);
    }
}

/// 分页响应
#[derive(Debug, Serialize, utoipa::ToSchema)]
pub struct PaginatedResponse<T> {
    pub data: Vec<T>,
    pub total: u64,
    pub page: u64,
    pub page_size: u64,
    pub total_pages: u64,
}

/// API 统一响应
#[derive(Debug, Serialize, utoipa::ToSchema)]
pub struct ApiResponse<T: Serialize> {
    pub success: bool,
    pub data: Option<T>,
    pub message: Option<String>,
}

impl<T: Serialize> ApiResponse<T> {
    pub fn ok(data: T) -> Self {
        Self {
            success: true,
            data: Some(data),
            message: None,
        }
    }
}

/// 行级数据权限范围
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum DataScope {
    /// 查看所有数据
    All,
    /// 仅查看自己创建的数据
    SelfOnly,
    /// 仅查看本部门数据
    Department,
    /// 查看本部门及下属部门数据
    DepartmentTree,
}

impl DataScope {
    pub fn parse_scope(s: &str) -> Self {
        match s {
            "self" => Self::SelfOnly,
            "department" => Self::Department,
            "department_tree" => Self::DepartmentTree,
            _ => Self::All,
        }
    }
}

/// 租户上下文（中间件注入）
#[derive(Debug, Clone)]
pub struct TenantContext {
    pub tenant_id: Uuid,
    pub user_id: Uuid,
    pub roles: Vec<String>,
    pub permissions: Vec<String>,
    /// 用户所属部门 ID 列表（行级数据权限使用）
    pub department_ids: Vec<Uuid>,
    /// 每个权限码对应的数据范围（从 role_permissions.data_scope 加载）
    pub permission_data_scopes: HashMap<String, DataScope>,
}
