"""FastAPI Router for JMAP (RFC 8620 & RFC 8621) Endpoints."""

from __future__ import annotations

import logging
from typing import Any, Dict

from fastapi import APIRouter, Depends, Header, HTTPException, Request, Response, status
from fastapi.responses import JSONResponse, RedirectResponse

from ..jmap_engine import get_jmap_session, process_jmap_request
from ..settings import get_settings

logger = logging.getLogger(__name__)

router = APIRouter(tags=["jmap"])


def get_jmap_user(request: Request, authorization: str = Header(None)) -> str:
    """Extract and verify authenticated username from panel session, Basic Auth, or Bearer Token."""
    # 1. Active Panel Session
    try:
        from .admin import load_panel_session

        sess = load_panel_session(request)
        if sess and isinstance(sess, dict) and sess.get("username"):
            return sess["username"]
    except Exception:
        pass

    # 2. HTTP Basic Auth (username:password)
    if authorization and authorization.lower().startswith("basic "):
        try:
            import base64

            encoded = authorization.split(" ", 1)[1]
            decoded = base64.b64decode(encoded).decode("utf-8")
            if ":" in decoded:
                user, password = decoded.split(":", 1)
                if user and password:
                    from ..db import SessionLocal
                    from ..models import Account
                    from ..security import verify_password
                    from ..settings import get_settings

                    settings = get_settings()

                    # Admin check
                    if user.lower() == f"admin@{settings.hostname}".lower() or user.lower() == settings.api_admin_user.lower():
                        from ..security import verify_admin_password
                        if verify_admin_password(password):
                            return f"admin@{settings.hostname}"

                    # Account mailbox credentials check
                    db = SessionLocal()
                    try:
                        acc = db.query(Account).filter(Account.username == user.lower()).first()
                        if acc and acc.is_active and verify_password(password, acc.password_hash):
                            return acc.username
                    finally:
                        db.close()
        except Exception as exc:
            logger.debug("JMAP Basic Auth verification error: %s", exc)

    # 3. If unauthenticated, raise 401 Unauthorized
    raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Authentication required to access JMAP session",
        headers={"WWW-Authenticate": 'Basic realm="JMAP Authentication"'},
    )


@router.get("/.well-known/jmap")
def jmap_well_known(request: Request):
    """RFC 8620 Section 2.1 Well-Known JMAP Location Discovery."""
    return RedirectResponse(url="/jmap/session", status_code=status.HTTP_307_TEMPORARY_REDIRECT)


@router.get("/jmap")
@router.get("/jmap/session")
@router.get("/api/jmap/session")
def jmap_session_endpoint(request: Request, username: str = Depends(get_jmap_user)):
    """RFC 8620 Section 2.2 JMAP Session Resource."""
    host = request.headers.get("host", get_settings().hostname)
    is_secure = request.url.scheme == "https"
    session_data = get_jmap_session(username=username, host=host, is_secure=is_secure)
    return JSONResponse(content=session_data, headers={"Cache-Control": "no-cache, no-store"})


@router.post("/jmap/api")
@router.post("/api/jmap/api")
async def jmap_api_endpoint(request: Request, username: str = Depends(get_jmap_user)):
    """RFC 8620 Section 3 JMAP Request Processing."""
    try:
        payload = await request.json()
    except Exception as exc:
        raise HTTPException(
            status_code=400,
            detail={"type": "urn:ietf:params:jmap:error:notJSON", "status": 400, "detail": "Request body must be valid JSON"},
        ) from exc

    if not isinstance(payload, dict):
        raise HTTPException(
            status_code=400,
            detail={"type": "urn:ietf:params:jmap:error:notRequest", "status": 400, "detail": "Request body must be a JSON object"},
        )

    response_data = process_jmap_request(payload, username)
    return JSONResponse(content=response_data, media_type="application/json")


@router.get("/jmap/download/{account_id}/{blob_id}/{name}")
@router.get("/api/jmap/download/{account_id}/{blob_id}/{name}")
def jmap_download_blob(account_id: str, blob_id: str, name: str, request: Request, username: str = Depends(get_jmap_user)):
    """RFC 8620 Section 6 JMAP Blob Downloading."""
    return Response(content=b"", media_type="application/octet-stream", headers={"Content-Disposition": f'attachment; filename="{name}"'})


@router.post("/jmap/upload/{account_id}")
@router.post("/api/jmap/upload/{account_id}")
async def jmap_upload_blob(account_id: str, request: Request, username: str = Depends(get_jmap_user)):
    """RFC 8620 Section 6 JMAP Blob Uploading."""
    body = await request.body()
    import hashlib
    blob_id = hashlib.sha256(body).hexdigest()[:16]
    return JSONResponse(content={"accountId": account_id, "blobId": blob_id, "size": len(body), "type": "application/octet-stream"})
