from __future__ import annotations

from typing import Annotated

from fastapi import APIRouter, Depends, Response
from fastapi import HTTPException

from core.auth.models import CurrentUser
from v1.auth.rate_limit import enforce_rate_limit
from v1.auth.dependencies import get_auth_service
from v1.users.dependencies import get_current_user
from v1.auth.schemas import (
    PasswordResetConfirmRequest,
    PasswordResetRequest,
    SessionCreateRequest,
    SessionDeleteRequest,
    SessionRefreshRequest,
    SessionResponse,
    UserByEmailResponse,
    VerificationCreateRequest,
    VerificationCreateResponse,
    VerificationResendRequest,
    VerificationVerifyRequest,
)
from v1.auth.service import AuthService


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


@router.post(
    "/verifications", response_model=VerificationCreateResponse, status_code=202
)
async def create_verification(
    payload: VerificationCreateRequest,
    service: AuthService = Depends(get_auth_service),
) -> VerificationCreateResponse:
    await enforce_rate_limit(
        scope="signup_start",
        identifier=payload.email,
        limit=5,
        window_seconds=60,
    )
    return await service.create_verification(payload)


@router.post("/verifications/verify", response_model=SessionResponse)
async def verify_verification(
    payload: VerificationVerifyRequest,
    service: AuthService = Depends(get_auth_service),
) -> SessionResponse:
    await enforce_rate_limit(
        scope="signup_verify",
        identifier=payload.email,
        limit=10,
        window_seconds=600,
    )
    return await service.verify_verification(payload)


@router.post("/verifications/resend", status_code=204)
async def resend_verification(
    payload: VerificationResendRequest,
    service: AuthService = Depends(get_auth_service),
) -> Response:
    await enforce_rate_limit(
        scope="signup_resend",
        identifier=payload.email,
        limit=5,
        window_seconds=60,
    )
    await service.resend_verification(payload)
    return Response(status_code=204)


@router.post("/sessions", response_model=SessionResponse)
async def create_session(
    payload: SessionCreateRequest,
    service: AuthService = Depends(get_auth_service),
) -> SessionResponse:
    await enforce_rate_limit(
        scope="login",
        identifier=payload.email,
        limit=10,
        window_seconds=60,
    )
    return await service.create_session(payload)


@router.post("/sessions/refresh", response_model=SessionResponse)
async def refresh_session(
    payload: SessionRefreshRequest,
    service: AuthService = Depends(get_auth_service),
) -> SessionResponse:
    await enforce_rate_limit(
        scope="refresh",
        identifier=payload.refresh_token,
        limit=10,
        window_seconds=60,
    )
    return await service.refresh_session(payload)


@router.delete("/sessions", status_code=204)
async def delete_session(
    payload: SessionDeleteRequest,
    service: AuthService = Depends(get_auth_service),
) -> Response:
    await enforce_rate_limit(
        scope="logout",
        identifier=payload.refresh_token,
        limit=10,
        window_seconds=60,
    )
    await service.delete_session(payload.refresh_token)
    return Response(status_code=204)


@router.get("/users", response_model=UserByEmailResponse)
async def get_user_by_email(
    email: str,
    current_user: Annotated[CurrentUser, Depends(get_current_user)],
    service: AuthService = Depends(get_auth_service),
) -> UserByEmailResponse:
    if current_user.role != "service_role" and current_user.email != email:
        raise HTTPException(status_code=403, detail="Forbidden")
    return await service.get_user_by_email(email)


@router.post("/password-reset", status_code=204)
async def request_password_reset(
    payload: PasswordResetRequest,
    service: AuthService = Depends(get_auth_service),
) -> Response:
    await enforce_rate_limit(
        scope="password_reset_request",
        identifier=payload.email,
        limit=5,
        window_seconds=60,
    )
    await service.request_password_reset(payload)
    return Response(status_code=204)


@router.post("/password-reset/confirm", status_code=204)
async def confirm_password_reset(
    payload: PasswordResetConfirmRequest,
    service: AuthService = Depends(get_auth_service),
) -> Response:
    await enforce_rate_limit(
        scope="password_reset_confirm",
        identifier=payload.email,
        limit=10,
        window_seconds=600,
    )
    await service.confirm_password_reset(payload)
    return Response(status_code=204)
