from pydantic import BaseModel, Field, validator
from typing import Optional, List, Dict, Any
from datetime import datetime
from app.models.role import RoleType

class RoleCreate(BaseModel):
    name: str = Field(..., min_length=2, max_length=50)
    display_name: str = Field(..., min_length=2, max_length=100)
    description: Optional[str] = Field(None, max_length=500)
    role_type: RoleType = RoleType.CUSTOM
    permissions: List[str] = Field(default_factory=list)
    parent_role: Optional[str] = None
    max_users: Optional[int] = Field(None, gt=0)
    color: Optional[str] = Field(None, regex="^#[0-9A-Fa-f]{6}$")
    priority: int = Field(100, ge=0, le=1000)
    custom_properties: Optional[Dict[str, Any]] = None

    @validator('name')
    def validate_name(cls, v):
        # Role name should be lowercase and no spaces
        if not v.replace('_', '').replace('-', '').isalnum():
            raise ValueError('Role name can only contain letters, numbers, hyphens, and underscores')
        return v.lower()

class RoleUpdate(BaseModel):
    display_name: Optional[str] = Field(None, min_length=2, max_length=100)
    description: Optional[str] = Field(None, max_length=500)
    permissions: Optional[List[str]] = None
    parent_role: Optional[str] = None
    max_users: Optional[int] = Field(None, gt=0)
    is_active: Optional[bool] = None
    color: Optional[str] = Field(None, regex="^#[0-9A-Fa-f]{6}$")
    priority: Optional[int] = Field(None, ge=0, le=1000)
    custom_properties: Optional[Dict[str, Any]] = None

class RoleResponse(BaseModel):
    id: str
    name: str
    display_name: str
    description: Optional[str] = None
    role_type: RoleType
    is_active: bool
    is_default: bool
    is_system_role: bool
    permissions: List[str]
    parent_role: Optional[str] = None
    child_roles: List[str]
    max_users: Optional[int] = None
    user_count: int = 0
    expires_at: Optional[datetime] = None
    created_at: datetime
    updated_at: datetime
    created_by: Optional[str] = None
    color: Optional[str] = None
    priority: int
    custom_properties: Dict[str, Any]

    class Config:
        from_attributes = True

class AssignRoleRequest(BaseModel):
    user_id: str
    role_name: str
    expires_in_days: Optional[int] = Field(None, gt=0)
    scope: Optional[str] = None
    notes: Optional[str] = Field(None, max_length=500)

class RevokeRoleRequest(BaseModel):
    user_id: str
    role_name: str
    reason: Optional[str] = Field(None, max_length=500)

class UserRoleResponse(BaseModel):
    id: str
    user_id: str
    role_name: str
    role_display_name: str
    assigned_by: Optional[str] = None
    assigned_at: datetime
    is_active: bool
    expires_at: Optional[datetime] = None
    is_permanent: bool
    scope: Optional[str] = None
    notes: Optional[str] = None
    revoked_at: Optional[datetime] = None
    revoked_by: Optional[str] = None
    revocation_reason: Optional[str] = None

    class Config:
        from_attributes = True

class RolePermissionUpdate(BaseModel):
    permission_name: str
    action: str = Field(..., regex="^(add|remove)$")

class BulkRoleAssignment(BaseModel):
    user_ids: List[str] = Field(..., min_items=1)
    role_name: str
    expires_in_days: Optional[int] = Field(None, gt=0)
    notes: Optional[str] = Field(None, max_length=500)

class RoleHierarchyResponse(BaseModel):
    name: str
    display_name: str
    children: List["RoleHierarchyResponse"] = Field(default_factory=list)
    permissions: List[str]
    user_count: int

# Update forward reference

class RoleStatsResponse(BaseModel):
    total_roles: int
    system_roles: int
    custom_roles: int
    active_roles: int
    role_assignments: int
    most_assigned_roles: List[Dict[str, Any]]
    recent_assignments: int
