from __future__ import annotations

from typing import Annotated

from fastapi import Depends, Request

from backend.features.accounts.models import Principal
from backend.http.errors import AppError

SESSION_COOKIE = "xiaobai_session"
CSRF_COOKIE = "xiaobai_csrf"


def require_principal(request: Request) -> Principal:
    service = request.app.state.container.accounts
    principal = service.authenticate(request.cookies.get(SESSION_COOKIE))
    if principal is None:
        raise AppError("authentication_required", "请先登录。", 401)
    return principal


AuthenticatedPrincipal = Annotated[Principal, Depends(require_principal)]


def require_csrf(
    request: Request,
    principal: AuthenticatedPrincipal,
) -> Principal:
    valid = request.app.state.container.accounts.verify_csrf(
        principal,
        request.headers.get("X-CSRF-Token"),
        request.cookies.get(CSRF_COOKIE),
    )
    if not valid:
        raise AppError("csrf_failed", "页面状态已过期，请刷新后重试。", 403)
    return principal


CsrfPrincipal = Annotated[Principal, Depends(require_csrf)]


def require_admin(principal: AuthenticatedPrincipal) -> Principal:
    if not principal.user.is_admin:
        raise AppError("access_denied", "当前账号无权执行此操作。", 403)
    return principal


def require_admin_write(principal: CsrfPrincipal) -> Principal:
    if not principal.user.is_admin:
        raise AppError("access_denied", "当前账号无权执行此操作。", 403)
    return principal


AdminPrincipal = Annotated[Principal, Depends(require_admin)]
AdminWritePrincipal = Annotated[Principal, Depends(require_admin_write)]


def require_smart_access(
    request: Request,
    principal: AuthenticatedPrincipal,
) -> Principal:
    if not request.app.state.container.memberships.can_use_smart_features(principal):
        raise AppError("membership_required", "该功能仅对会员开放。", 403)
    return principal


SmartAccessPrincipal = Annotated[Principal, Depends(require_smart_access)]


def require_smart_write(
    request: Request,
    principal: CsrfPrincipal,
) -> Principal:
    if not request.app.state.container.memberships.can_use_smart_features(principal):
        raise AppError("membership_required", "该功能仅对会员开放。", 403)
    return principal


SmartWritePrincipal = Annotated[Principal, Depends(require_smart_write)]
