"""
app/core/security.py — JWT + Fernet 工具函数
FERNET_KEY 走环境变量，绝不进代码库（基石B）。
"""

import logging
from datetime import datetime, timedelta, timezone
from typing import Any

import jwt
from cryptography.fernet import Fernet, InvalidToken

from app.core.config import get_settings

logger = logging.getLogger(__name__)
settings = get_settings()

# ── Fernet 加密（API Key 存取）──────────────────────────
_fernet: Fernet | None = None


def _get_fernet() -> Fernet:
    global _fernet
    if _fernet is None:
        _fernet = Fernet(settings.FERNET_KEY.encode())
    return _fernet


def encrypt_api_key(plain_key: str) -> str:
    """加密 API Key，返回密文字符串。绝不打印 plain_key。"""
    return _get_fernet().encrypt(plain_key.encode()).decode()


def decrypt_api_key(encrypted_key: str) -> str:
    """
    解密 API Key。只在 Celery worker 内部调用。
    解密结果只活在调用函数的局部变量，不落盘、不打日志。
    """
    try:
        return _get_fernet().decrypt(encrypted_key.encode()).decode()
    except InvalidToken:
        logger.error("Fernet decrypt failed: invalid token (key may be rotated)")
        raise ValueError("API key decryption failed")


# ── JWT ──────────────────────────────────────────────────
def create_access_token(
    user_id: int,
    workspace_id: int,
    role: str,
    expires_delta: timedelta | None = None,
) -> str:
    expire = datetime.now(timezone.utc) + (
        expires_delta or timedelta(minutes=settings.JWT_EXPIRE_MINUTES)
    )
    payload: dict[str, Any] = {
        "sub": str(user_id),
        "user_id": user_id,
        "current_workspace_id": workspace_id,
        "role": role,
        "exp": expire,
    }
    return jwt.encode(payload, settings.JWT_SECRET, algorithm="HS256")


def decode_access_token(token: str) -> dict[str, Any]:
    """验签并返回 payload。无效则抛 jwt.PyJWTError。"""
    return jwt.decode(token, settings.JWT_SECRET, algorithms=["HS256"])


def mask_api_key(plain_key: str) -> str:
    """只返回后4位（展示用），不暴露完整 key。"""
    return plain_key[-4:] if len(plain_key) >= 4 else "****"
