# =============================================================================
# 角色 Pydantic Schema
# =============================================================================
# 说明：定义角色相关的请求/响应数据结构
# 包含：角色响应、角色分配、角色映射规则等 Schema
# =============================================================================

from datetime import datetime
from typing import List, Optional

from pydantic import BaseModel, Field, field_validator


# --------------------------------------------------------------------------
# 角色响应 Schema
# --------------------------------------------------------------------------
class RoleResponse(BaseModel):
    """角色响应 Schema。

    Attributes:
        id: 角色ID
        name: 角色标识（user/agent/admin）
        display_name: 显示名称（用户/坐席/管理员）
        description: 角色描述
        permissions: 权限列表
        is_default: 是否默认角色
        user_count: 拥有该角色的用户数（可选）
        created_at: 创建时间
        updated_at: 更新时间
    """

    id: str
    name: str
    display_name: str
    description: Optional[str] = None
    permissions: List[str] = []
    is_default: bool = False
    user_count: Optional[int] = None
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


# --------------------------------------------------------------------------
# 用户角色响应 Schema
# --------------------------------------------------------------------------
class UserRoleResponse(BaseModel):
    """用户角色响应 Schema。

    Attributes:
        id: 记录ID
        employee_id: 企微 UserID
        role_id: 角色 ID
        role_name: 角色标识
        role_display_name: 角色显示名称
        source: 角色来源（auto/tag/ehr/manual）
        assigned_by: 分配者
        assigned_at: 分配时间
        expires_at: 过期时间
    """

    id: str
    employee_id: str
    role_id: str
    role_name: str
    role_display_name: str
    source: str
    assigned_by: Optional[str] = None
    assigned_at: datetime
    expires_at: Optional[datetime] = None

    model_config = {"from_attributes": True}


# --------------------------------------------------------------------------
# 角色分配请求 Schema
# --------------------------------------------------------------------------
class RoleAssignRequest(BaseModel):
    """角色分配请求 Schema。

    Attributes:
        employee_id: 企微 UserID
        role_name: 角色标识（user/agent/admin）
        reason: 分配原因（可选）
    """

    employee_id: str = Field(..., min_length=1, max_length=100, description="企微 UserID")
    role_name: str = Field(..., min_length=1, max_length=50, description="角色标识")
    reason: Optional[str] = Field(None, max_length=500, description="分配原因")


# --------------------------------------------------------------------------
# 角色撤销请求 Schema
# --------------------------------------------------------------------------
class RoleRevokeRequest(BaseModel):
    """角色撤销请求 Schema。

    Attributes:
        employee_id: 企微 UserID
        role_name: 角色标识（user/agent/admin）
        reason: 撤销原因（可选）
    """

    employee_id: str = Field(..., min_length=1, max_length=100, description="企微 UserID")
    role_name: str = Field(..., min_length=1, max_length=50, description="角色标识")
    reason: Optional[str] = Field(None, max_length=500, description="撤销原因")


# --------------------------------------------------------------------------
# 角色映射规则响应 Schema
# --------------------------------------------------------------------------
class RoleMappingRuleResponse(BaseModel):
    """角色映射规则响应 Schema。

    Attributes:
        id: 规则ID
        role_id: 目标角色 ID
        role_name: 目标角色标识
        source_type: 来源类型（wecom_tag/ehr_position）
        source_value: 来源值（标签名/岗位关键词）
        priority: 优先级
        is_active: 是否启用
        created_at: 创建时间
    """

    id: str
    role_id: str
    role_name: str
    source_type: str
    source_value: str
    priority: int = 0
    is_active: bool = True
    created_at: datetime

    model_config = {"from_attributes": True}


# --------------------------------------------------------------------------
# 角色映射规则创建/更新请求 Schema
# --------------------------------------------------------------------------
class RoleMappingRuleRequest(BaseModel):
    """角色映射规则创建/更新请求 Schema。

    Attributes:
        role_name: 目标角色标识（user/agent/admin）
        source_type: 来源类型（wecom_tag/ehr_position）
        source_value: 来源值（标签名/岗位关键词）
        priority: 优先级（数值越大优先级越高）
        is_active: 是否启用
    """

    role_name: str = Field(..., min_length=1, max_length=50, description="目标角色标识")
    source_type: str = Field(..., min_length=1, max_length=50, description="来源类型")
    source_value: str = Field(..., min_length=1, max_length=200, description="来源值")
    priority: int = Field(0, ge=0, le=100, description="优先级（0-100）")
    is_active: bool = Field(True, description="是否启用")

    @field_validator("source_type")
    @classmethod
    def validate_source_type(cls, v: str) -> str:
        """校验来源类型是否合法。"""
        allowed_types = {"wecom_tag", "ehr_position"}
        if v not in allowed_types:
            raise ValueError(f"无效的来源类型: {v}，合法值为: {allowed_types}")
        return v

    @field_validator("role_name")
    @classmethod
    def validate_role_name(cls, v: str) -> str:
        """校验角色标识是否合法。"""
        allowed_roles = {"user", "agent", "admin"}
        if v not in allowed_roles:
            raise ValueError(f"无效的角色标识: {v}，合法值为: {allowed_roles}")
        return v

    @field_validator("source_value")
    @classmethod
    def validate_source_value(cls, v: str) -> str:
        """校验来源值是否包含恶意内容。"""
        # 过滤特殊字符
        forbidden_chars = {"<", ">", ";", "'", '"', "\\", "/", "(", ")"}
        for char in v:
            if char in forbidden_chars:
                raise ValueError(f"来源值包含非法字符: {char}")
        return v


# --------------------------------------------------------------------------
# Portal 用户信息响应 Schema
# --------------------------------------------------------------------------
class PortalUserInfo(BaseModel):
    """Portal 用户信息响应 Schema。

    用于路由选择页展示用户信息和角色列表。

    Attributes:
        employee_id: 企微 UserID
        name: 姓名
        department: 部门
        avatar: 头像URL
        roles: 角色列表
        current_role: 当前选择的角色
    """

    employee_id: str
    name: str
    department: Optional[str] = None
    avatar: Optional[str] = None
    roles: List[RoleResponse] = []
    current_role: str = "user"


# --------------------------------------------------------------------------
# 角色切换请求 Schema
# --------------------------------------------------------------------------
class SwitchRoleRequest(BaseModel):
    """角色切换请求 Schema。

    Attributes:
        new_role: 目标角色标识
    """

    new_role: str = Field(..., min_length=1, max_length=50, description="目标角色标识")


# --------------------------------------------------------------------------
# 角色切换响应 Schema
# --------------------------------------------------------------------------
class SwitchRoleResponse(BaseModel):
    """角色切换响应 Schema。

    Attributes:
        current_role: 切换后的角色标识
        redirect_url: 重定向URL
    """

    current_role: str
    redirect_url: str
