"""Security primitives: password hashing, JWT, CSRF, rate limiting, audit logging."""
import hashlib
import secrets
import time
from datetime import datetime, timedelta, timezone
from typing import Optional

import jwt
import bcrypt as _bcrypt
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.config import settings

# passlib 1.7.4 is incompatible with bcrypt >= 4.1; use bcrypt directly.
# Hashes remain standard $2b$ bcrypt, fully inter-operable.
_BCRYPT_ROUNDS = 12


def hash_password(p: str) -> str:
    pw = p.encode("utf-8")[:72]  # bcrypt input limit
    return _bcrypt.hashpw(pw, _bcrypt.gensalt(rounds=_BCRYPT_ROUNDS)).decode("ascii")


def verify_password(plain: str, hashed: str) -> bool:
    try:
        return _bcrypt.checkpw(plain.encode("utf-8")[:72], hashed.encode("ascii"))
    except Exception:
        return False

# Sensitive values that must never appear in logs or JSON responses.
SENSITIVE_KEYS = {"password", "client_secret", "refresh_token", "authorization_code",
                  "access_token", "secret", "token", "csrf", "new_password", "old_password"}


def hash_password(p: str) -> str:
    return pwd_context.hash(p)


def verify_password(plain: str, hashed: str) -> bool:
    try:
        return pwd_context.verify(plain, hashed)
    except Exception:
        return False


def create_access_token(user_id: int, expires_minutes: Optional[int] = None) -> str:
    payload = {
        "sub": str(user_id),
        "iat": int(time.time()),
