from __future__ import annotations

from datetime import datetime

from pydantic import BaseModel, Field

from ...core.permissions import MenuPermission, menus_for_role, permissions_for_role
from ...database.orm import UserORM
from ...services import AuthSession


class MenuDTO(BaseModel):
    """返回给前端的菜单项。"""

    code: str
    name: str
    path: str

    @classmethod
    def from_domain(cls, menu: MenuPermission) -> "MenuDTO":
        return cls(code=menu.code, name=menu.name, path=menu.path)


class UserProfileDTO(BaseModel):
    """当前登录用户及其权限上下文。"""

    id: int
    username: str
    display_name: str
    avatar_url: str
    email: str
    phone: str
    department: str
    position_title: str
    role: str
    is_active: bool
    menus: list[MenuDTO]
    permissions: list[str]

    @classmethod
    def from_orm_model(cls, user: UserORM) -> "UserProfileDTO":
        menus, permissions = _role_access(user.role)
        return cls(
            id=user.id,
            username=user.username,
            display_name=user.display_name,
            avatar_url=user.avatar_url,
            email=user.email,
            phone=user.phone,
            department=user.department,
            position_title=user.position_title,
            role=user.role,
            is_active=user.is_active,
            menus=menus,
            permissions=permissions,
        )


class LoginRequest(BaseModel):
    """登录请求。"""

    username: str
    password: str


class LoginResponse(BaseModel):
    """登录响应，前端据此渲染菜单和按钮权限。"""

    access_token: str
    token_type: str
    user: UserProfileDTO
    menus: list[MenuDTO]
    permissions: list[str]

    @classmethod
    def from_session(cls, session: AuthSession) -> "LoginResponse":
        user = UserProfileDTO.from_orm_model(session.user)
        return cls(
            access_token=session.access_token,
            token_type=session.token_type,
            user=user,
            menus=user.menus,
            permissions=user.permissions,
        )


class CreateUserRequest(BaseModel):
    """创建用户请求，角色只能取 permissions.py 中定义的角色。"""

    username: str = Field(..., min_length=2, max_length=64)
    password: str = Field(..., min_length=6, max_length=128)
    role: str
    display_name: str = ""
    email: str = Field(default="", max_length=128)
    phone: str = Field(default="", max_length=32)
    department: str = Field(default="", max_length=128)
    position_title: str = Field(default="", max_length=128)


class ChangePasswordRequest(BaseModel):
    """当前登录用户修改自己密码请求。"""

    old_password: str = Field(..., min_length=1, max_length=128)
    new_password: str = Field(..., min_length=6, max_length=128)
    confirm_password: str = Field(..., min_length=6, max_length=128)


class ChangePasswordResponse(BaseModel):
    """修改密码成功响应。"""

    message: str


class UserResponse(BaseModel):
    """用户管理列表/创建接口的返回模型。"""

    id: int
    username: str
    display_name: str
    avatar_url: str
    email: str
    phone: str
    department: str
    position_title: str
    role: str
    is_active: bool
    created_at: datetime
    updated_at: datetime
    menus: list[MenuDTO]
    permissions: list[str]

    @classmethod
    def from_orm_model(cls, user: UserORM) -> "UserResponse":
        profile = UserProfileDTO.from_orm_model(user)
        return cls(
            id=user.id,
            username=user.username,
            display_name=user.display_name,
            avatar_url=user.avatar_url,
            email=user.email,
            phone=user.phone,
            department=user.department,
            position_title=user.position_title,
            role=user.role,
            is_active=user.is_active,
            created_at=user.created_at,
            updated_at=user.updated_at,
            menus=profile.menus,
            permissions=profile.permissions,
        )


class UpdateProfileRequest(BaseModel):
    """当前登录用户修改个人资料请求。"""

    display_name: str = Field(default="", max_length=128)
    email: str = Field(default="", max_length=128)
    phone: str = Field(default="", max_length=32)
    department: str = Field(default="", max_length=128)
    position_title: str = Field(default="", max_length=128)


def _role_access(role: str) -> tuple[list[MenuDTO], list[str]]:
    """统一生成前端菜单和按钮/接口操作权限，避免响应模型各自拼装。"""
    return (
        [MenuDTO.from_domain(menu) for menu in menus_for_role(role)],
        permissions_for_role(role),
    )
