"""Platform-admin auth — same JWT/session model as public auth, stricter entry points."""
from __future__ import annotations

from typing import Optional

from fastapi import APIRouter, Depends, Query, Request, Response
from fastapi.security import HTTPAuthorizationCredentials
from sqlalchemy.ext.asyncio import AsyncSession

from src.config import get_settings
from src.core.app_url import resolve_app_base_url
from src.core.database import get_db
from src.core.exceptions import ForbiddenError, UnauthorizedError
from src.core.security.jwt import get_user_id_from_token
from src.domain.admin.repository import AdminRepository
from src.domain.auth.bootstrap_service import AuthBootstrapService
from src.domain.auth.models import User
from src.domain.auth.repository import UserRepository
from src.domain.auth.router import (
    TRUSTED_DEVICE_COOKIE,
    MagicVerifyResponse,
    TotpCompleteMfaRequest,
    get_auth_service,
    get_bootstrap_service,
    security,
)
from src.domain.auth.schemas import (
    MagicLinkRequest,
    MagicLinkVerify,
    RefreshRequest,
    TokenResponse,
    magic_verify_success_envelope,
)
from src.domain.auth.service import AuthService

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


async def _user_must_be_platform_admin(
    db: AsyncSession,
    auth_service: AuthService,
    tokens: TokenResponse,
) -> User:
    """If the access token user is not in ``admins``, revoke the fresh session and forbid."""
    uid = get_user_id_from_token(tokens.access_token)
    if not uid:
        await auth_service.logout(refresh_token=tokens.refresh_token)
        raise UnauthorizedError("Invalid token state after login")
    user_repo = UserRepository(db)
    user = await user_repo.get_by_id(uid)
    if not user:
        await auth_service.logout(refresh_token=tokens.refresh_token)
        raise UnauthorizedError("User not found")
    admin_repo = AdminRepository(db)
    if not await admin_repo.is_admin(user.id):
        await auth_service.logout(refresh_token=tokens.refresh_token)
        raise ForbiddenError(
            "Platform admin access required. Sign in with an account that has platform admin."
        )
    return user


@router.post("/magic/request")
async def admin_magic_request(
    body: MagicLinkRequest,
    request: Request,
    db: AsyncSession = Depends(get_db),
    auth_service: AuthService = Depends(get_auth_service),
):
    """Send a magic link only when the email belongs to an existing **platform admin** user."""
    user_repo = UserRepository(db)
    admin_repo = AdminRepository(db)
    email = body.email.strip().lower()
    user = await user_repo.get_by_email(email)
    if not user or not await admin_repo.is_admin(user.id):
        # Do not reveal whether the address exists / is admin.
        return {"message": "If this email is registered as a platform admin, a sign-in link was sent."}

    settings = get_settings()
    token = await auth_service.request_magic_link(
        email,
        ip_address=request.client.host if request.client else None,
        app_base_url=resolve_app_base_url(request),
    )
    out: dict = {"message": "Magic link sent"}
    if settings.auth_expose_magic_token_for_dev or settings.debug:
        out["token_preview"] = f"{token[:8]}..."
    return out


@router.post("/magic/verify", response_model=MagicVerifyResponse)
async def admin_magic_verify_post(
    body: MagicLinkVerify,
    request: Request,
    db: AsyncSession = Depends(get_db),
    auth_service: AuthService = Depends(get_auth_service),
    bootstrap: AuthBootstrapService = Depends(get_bootstrap_service),
):
    """Verify magic link and return JWTs **only** for platform admins (others get 403; session revoked)."""
    device_id = request.cookies.get(TRUSTED_DEVICE_COOKIE)
    result = await auth_service.verify_magic_link(
        token=body.token,
        ip_address=request.client.host if request.client else None,
        user_agent=request.headers.get("user-agent"),
        device_id=device_id,
    )
    if not isinstance(result, tuple):
        return result
    tokens, _user = result
    user = await _user_must_be_platform_admin(db, auth_service, tokens)
    payload = await bootstrap.build_bootstrap(user)
    return magic_verify_success_envelope(tokens, payload)


@router.get("/magic/verify", response_model=MagicVerifyResponse)
async def admin_magic_verify_get(
    request: Request,
    token: str = Query(...),
    db: AsyncSession = Depends(get_db),
    auth_service: AuthService = Depends(get_auth_service),
    bootstrap: AuthBootstrapService = Depends(get_bootstrap_service),
):
    """Verify magic link via GET (same rules as POST)."""
    device_id = request.cookies.get(TRUSTED_DEVICE_COOKIE)
    result = await auth_service.verify_magic_link(
        token=token,
        ip_address=request.client.host if request.client else None,
        user_agent=request.headers.get("user-agent"),
        device_id=device_id,
    )
    if not isinstance(result, tuple):
        return result
    tokens, _user = result
    user = await _user_must_be_platform_admin(db, auth_service, tokens)
    payload = await bootstrap.build_bootstrap(user)
    return magic_verify_success_envelope(tokens, payload)


@router.post("/mfa/totp/verify")
async def admin_totp_verify(
    body: TotpCompleteMfaRequest,
    request: Request,
    response: Response,
    db: AsyncSession = Depends(get_db),
    auth_service: AuthService = Depends(get_auth_service),
    bootstrap: AuthBootstrapService = Depends(get_bootstrap_service),
):
    """Complete MFA after ``/api/admin/auth/magic/verify`` returned an MFA challenge."""
    token = body.mfa_token or body.login_token
    if not token:
        raise UnauthorizedError("mfa_token or login_token required")
    result = await auth_service.complete_totp_mfa(
        mfa_token=token,
        code=body.code,
        remember_device=body.remember_device,
        device_id=request.cookies.get(TRUSTED_DEVICE_COOKIE),
        user_agent=request.headers.get("user-agent"),
        ip_address=request.client.host if request.client else None,
    )
    if not result:
        raise UnauthorizedError("Invalid MFA token or code")
    tokens, trusted_device_id, used_backup_code, backup_codes_remaining = result
    user = await _user_must_be_platform_admin(db, auth_service, tokens)

    settings = get_settings()
    if trusted_device_id:
        response.set_cookie(
            key=TRUSTED_DEVICE_COOKIE,
            value=trusted_device_id,
            httponly=False,
            secure=not settings.is_dev,
            samesite="lax",
            max_age=60 * 60 * 24 * 30,
        )
    payload = await bootstrap.build_bootstrap(user)
    out = {
        "success": True,
        "access_token": tokens.access_token,
        "refresh_token": tokens.refresh_token,
        "token_type": tokens.token_type,
        "expires_in": tokens.expires_in,
        "issued_at": tokens.issued_at.isoformat() if tokens.issued_at else None,
        "two_factor_verified": True,
        "user": payload["user"],
        "session": payload["session"],
        "workspaces": payload["workspaces"],
        "routing": payload["routing"],
    }
    if used_backup_code:
        out["used_backup_code"] = True
    if backup_codes_remaining is not None:
        out["backup_codes_remaining"] = backup_codes_remaining
    if trusted_device_id:
        out["trusted_device_token"] = trusted_device_id
    return out


@router.get("/bootstrap")
async def admin_auth_bootstrap(
    credentials: Optional[HTTPAuthorizationCredentials] = Depends(security),
    auth_service: AuthService = Depends(get_auth_service),
    bootstrap: AuthBootstrapService = Depends(get_bootstrap_service),
    db: AsyncSession = Depends(get_db),
):
    """Full bootstrap for an already-authenticated **platform admin** (403 if not admin)."""
    if not credentials or not credentials.credentials:
        raise UnauthorizedError("Send Authorization: Bearer <access_token>.")
    user = await auth_service.get_current_user(credentials.credentials)
    if not user:
        raise UnauthorizedError("Invalid or expired access token.")
    admin_repo = AdminRepository(db)
    if not await admin_repo.is_admin(user.id):
        raise ForbiddenError("Platform admin access required")
    payload = await bootstrap.build_bootstrap(user)
    payload["success"] = True
    return payload


@router.post("/refresh", response_model=TokenResponse)
async def admin_refresh(
    body: RefreshRequest,
    db: AsyncSession = Depends(get_db),
    auth_service: AuthService = Depends(get_auth_service),
):
    """Rotate JWTs only when the subject user is a platform admin."""
    try:
        tokens = await auth_service.refresh_tokens(body.refresh_token)
    except Exception as e:
        if hasattr(e, "message"):
            raise UnauthorizedError(e.message)
        raise
    await _user_must_be_platform_admin(db, auth_service, tokens)
    return tokens
