from datetime import datetime, timezone
from typing import Any
from uuid import UUID

from fastapi import APIRouter, Depends, Request
from pydantic import BaseModel, EmailStr, Field
from sqlalchemy.ext.asyncio import AsyncSession

from src.domain.entities import UserRole
from src.infrastructure.database.session import get_db_session
from src.services.auth.auth_service import AuthService
from src.api.v1.dependencies.auth import get_auth_service, get_current_user, require_role
from src.services.auth.security import TokenData

router = APIRouter(prefix="/auth", tags=["Authentication"])


class LoginRequest(BaseModel):
    username: str = Field(..., min_length=3, max_length=100)
    password: str = Field(..., min_length=8)


class RegisterRequest(BaseModel):
    username: str = Field(..., min_length=3, max_length=100, pattern=r"^[A-Za-z0-9_]+$")
    password: str = Field(..., min_length=8)
    email: EmailStr | None = None
    full_name: str | None = None
    role: UserRole = UserRole.VIEWER


class TokenResponse(BaseModel):
    access_token: str
    refresh_token: str
    token_type: str = "bearer"
    expires_in: int


class RefreshRequest(BaseModel):
    refresh_token: str


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 MeResponse(BaseModel):
    id: UUID
    username: str
    email: str | None
    full_name: str | None
    role: str
    is_active: bool
    scopes: list[str]


@router.post("/register", response_model=UserResponse, status_code=201)
async def register(body: RegisterRequest, service: AuthService = Depends(get_auth_service)):
    user = await service.register(
        username=body.username,
        password=body.password,
        email=body.email,
        full_name=body.full_name,
        role=body.role,
    )
    return UserResponse(
        id=user.id,
        username=user.username,
        email=user.email,
        full_name=user.full_name,
        role=user.role.value,
        is_active=user.is_active,
        scopes=user.scopes,
        last_login_at=user.last_login_at,
        created_at=user.created_at,
    )


@router.post("/token", response_model=TokenResponse)
async def login(body: LoginRequest, service: AuthService = Depends(get_auth_service)):
    user, access_token, refresh_token = await service.authenticate(body.username, body.password)
    return TokenResponse(
        access_token=access_token,
        refresh_token=refresh_token,
        expires_in=30 * 60,
    )


@router.post("/refresh", response_model=TokenResponse)
async def refresh_token(body: RefreshRequest, service: AuthService = Depends(get_auth_service)):
    access_token, refresh_token = await service.refresh_access_token(body.refresh_token)
    return TokenResponse(
        access_token=access_token,
        refresh_token=refresh_token,
        expires_in=30 * 60,
    )


@router.get("/me", response_model=MeResponse)
async def get_me(current_user: TokenData = Depends(get_current_user)):
    return MeResponse(
        id=UUID(current_user.subject),
        username="",
        email=None,
        full_name=None,
        role=current_user.role.value,
        is_active=True,
        scopes=current_user.scopes,
    )
