"""
Authentication routes for L2 server.

Handles login, registration, logout, and token verification.
"""

import hashlib
from datetime import datetime, timezone

from fastapi import APIRouter, Request, Form, HTTPException, Depends
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

from artdag_common import render
from artdag_common.middleware import wants_html

from ..config import settings
from ..dependencies import get_templates, get_user_from_cookie

router = APIRouter()
security = HTTPBearer(auto_error=False)


@router.get("/login", response_class=HTMLResponse)
async def login_page(request: Request, return_to: str = None):
    """Login page."""
    username = get_user_from_cookie(request)

    if username:
        templates = get_templates(request)
        return render(templates, "auth/already_logged_in.html", request,
            user={"username": username},
        )

    templates = get_templates(request)
    return render(templates, "auth/login.html", request,
        return_to=return_to,
    )


@router.post("/login", response_class=HTMLResponse)
async def login_submit(
    request: Request,
    username: str = Form(...),
    password: str = Form(...),
    return_to: str = Form(None),
):
    """Handle login form submission."""
    from auth import authenticate_user, create_access_token

    if not username or not password:
        return HTMLResponse(
            '<div class="text-red-400">Username and password are required</div>'
        )

    user = await authenticate_user(settings.data_dir, username.strip(), password)
    if not user:
        return HTMLResponse(
            '<div class="text-red-400">Invalid username or password</div>'
        )

    token = create_access_token(user.username, l2_server=f"https://{settings.domain}")

    # Handle return_to redirect
    if return_to and return_to.startswith("http"):
        separator = "&" if "?" in return_to else "?"
        redirect_url = f"{return_to}{separator}auth_token={token.access_token}"
        response = HTMLResponse(f'''
            <div class="text-green-400">Login successful! Redirecting...</div>
            <script>window.location.href = "{redirect_url}";</script>
        ''')
    else:
        response = HTMLResponse('''
            <div class="text-green-400">Login successful! Redirecting...</div>
            <script>window.location.href = "/";</script>
        ''')

    response.set_cookie(
        key="auth_token",
        value=token.access_token,
        httponly=True,
        max_age=60 * 60 * 24 * 30,
        samesite="lax",
        secure=True,
    )
    return response


@router.get("/register", response_class=HTMLResponse)
async def register_page(request: Request):
    """Registration page."""
    username = get_user_from_cookie(request)

    if username:
        templates = get_templates(request)
        return render(templates, "auth/already_logged_in.html", request,
            user={"username": username},
        )

    templates = get_templates(request)
    return render(templates, "auth/register.html", request)


@router.post("/register", response_class=HTMLResponse)
async def register_submit(
    request: Request,
    username: str = Form(...),
    password: str = Form(...),
    password2: str = Form(...),
    email: str = Form(None),
):
    """Handle registration form submission."""
    from auth import create_user, create_access_token

    if not username or not password:
        return HTMLResponse('<div class="text-red-400">Username and password are required</div>')

    if password != password2:
        return HTMLResponse('<div class="text-red-400">Passwords do not match</div>')

    if len(password) < 6:
        return HTMLResponse('<div class="text-red-400">Password must be at least 6 characters</div>')

    try:
        user = await create_user(settings.data_dir, username.strip(), password, email)
    except ValueError as e:
        return HTMLResponse(f'<div class="text-red-400">{str(e)}</div>')

    token = create_access_token(user.username, l2_server=f"https://{settings.domain}")

    response = HTMLResponse('''
        <div class="text-green-400">Registration successful! Redirecting...</div>
        <script>window.location.href = "/";</script>
    ''')
    response.set_cookie(
        key="auth_token",
        value=token.access_token,
        httponly=True,
        max_age=60 * 60 * 24 * 30,
        samesite="lax",
        secure=True,
    )
    return response


@router.get("/logout")
async def logout(request: Request):
    """Handle logout."""
    import db
    import requests
    from auth import get_token_claims

    token = request.cookies.get("auth_token")
    claims = get_token_claims(token) if token else None
    username = claims.get("sub") if claims else None

    if username and token and claims:
        # Revoke token in database
        token_hash = hashlib.sha256(token.encode()).hexdigest()
        expires_at = datetime.fromtimestamp(claims.get("exp", 0), tz=timezone.utc)
        await db.revoke_token(token_hash, username, expires_at)

        # Revoke on attached L1 servers
        attached = await db.get_user_renderers(username)
        for l1_url in attached:
            try:
                requests.post(
                    f"{l1_url}/auth/revoke-user",
                    json={"username": username, "l2_server": f"https://{settings.domain}"},
                    timeout=5,
                )
            except Exception:
                pass

    response = RedirectResponse(url="/", status_code=302)
    response.delete_cookie("auth_token")
    return response


@router.get("/verify")
async def verify_token(
    request: Request,
    credentials: HTTPAuthorizationCredentials = Depends(security),
):
    """
    Verify a token is valid.

    Called by L1 servers to verify tokens during auth callback.
    Returns user info if valid, 401 if not.
    """
    import db
    from auth import verify_token as verify_jwt, get_token_claims

    # Get token from Authorization header or query param
    token = None
    if credentials:
        token = credentials.credentials
    else:
        # Try Authorization header manually (for clients that don't use Bearer format)
        auth_header = request.headers.get("Authorization", "")
        if auth_header.startswith("Bearer "):
            token = auth_header[7:]

    if not token:
        raise HTTPException(401, "No token provided")

    # Verify JWT signature and expiry
    username = verify_jwt(token)
    if not username:
        raise HTTPException(401, "Invalid or expired token")

    # Check if token is revoked
    claims = get_token_claims(token)
    if claims:
        token_hash = hashlib.sha256(token.encode()).hexdigest()
        if await db.is_token_revoked(token_hash):
            raise HTTPException(401, "Token has been revoked")

    return {
        "valid": True,
        "username": username,
        "claims": claims,
    }
