from datetime import datetime
from uuid import UUID

from fastapi import APIRouter, Depends, Query
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession

from src.core.exceptions import NotFoundException
from src.domain.entities import TechnicalUserEntity, UserRole
from src.domain.interfaces import ITechnicalUserRepository
from src.infrastructure.database.repositories import TechnicalUserRepository
from src.infrastructure.database.session import get_db_session
from src.api.v1.dependencies.auth import get_current_user, require_role
from src.services.auth.security import TokenData

router = APIRouter(prefix="/users", tags=["Technical Users"])


class UserResponse(BaseModel):
    id: UUID
    username: str
    email: str | None
    full_name: str | None
    role: str
    is_active: bool
    scopes: list[str]
    last_login_at: datetime | None
    created_at: datetime | None


class UserListResponse(BaseModel):
    items: list[UserResponse]
    total: int
    offset: int
    limit: int


def _entity_to_response(e: TechnicalUserEntity) -> UserResponse:
    return UserResponse(
        id=e.id, username=e.username, email=e.email, full_name=e.full_name,
        role=e.role, is_active=e.is_active, scopes=e.scopes,
        last_login_at=e.last_login_at, created_at=e.created_at,
    )


@router.get("", response_model=UserListResponse)
async def list_users(
    role: str | None = None,
    is_active: bool | None = None,
    offset: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    session: AsyncSession = Depends(get_db_session),
    current_user: TokenData = Depends(require_role(UserRole.ADMIN)),
):
    repo = TechnicalUserRepository(session)
    entities, total = await repo.list_users(role=role, is_active=is_active, offset=offset, limit=limit)
    return UserListResponse(items=[_entity_to_response(e) for e in entities], total=total, offset=offset, limit=limit)


@router.get("/{user_id}", response_model=UserResponse)
async def get_user(
    user_id: UUID,
    session: AsyncSession = Depends(get_db_session),
    current_user: TokenData = Depends(require_role(UserRole.ADMIN)),
):
    repo = TechnicalUserRepository(session)
    entity = await repo.get_by_id(user_id)
    if not entity:
        raise NotFoundException("User", str(user_id))
    return _entity_to_response(entity)
