"""JWT + password utilities for the Narinest app API."""
import datetime
import os
import secrets

import bcrypt
import jwt

_SECRET = os.getenv('DJANGO_SECRET_KEY', 'change-me-in-production')
_ALGO = 'HS256'
_ACCESS_HOURS = 24 * 7   # 7 days
_REFRESH_DAYS = 30


# ── Password helpers ───────────────────────────────────────────────────────────

def hash_password(plain: str) -> str:
    return bcrypt.hashpw(plain.encode(), bcrypt.gensalt(12)).decode()


def check_password(plain: str, hashed: str) -> bool:
    try:
        return bcrypt.checkpw(plain.encode(), hashed.encode())
    except Exception:
        return False


# ── JWT helpers ────────────────────────────────────────────────────────────────

def make_access_token(user_id: int, role: str) -> str:
    return _encode({'sub': user_id, 'role': role, 'type': 'access'},
                   datetime.timedelta(hours=_ACCESS_HOURS))


def make_refresh_token(user_id: int, role: str) -> str:
    return _encode({'sub': user_id, 'role': role, 'type': 'refresh'},
                   datetime.timedelta(days=_REFRESH_DAYS))


def decode_token(token: str) -> dict | None:
    try:
        return jwt.decode(token, _SECRET, algorithms=[_ALGO])
    except jwt.ExpiredSignatureError:
        return None
    except jwt.InvalidTokenError:
        return None


def _encode(payload: dict, delta: datetime.timedelta) -> str:
    now = datetime.datetime.utcnow()
    payload.update({'iat': now, 'exp': now + delta})
    return jwt.encode(payload, _SECRET, algorithm=_ALGO)


# ── Reset code helpers ─────────────────────────────────────────────────────────

def make_reset_code() -> str:
    return ''.join(str(secrets.randbelow(10)) for _ in range(6))


def reset_code_expiry() -> datetime.datetime:
    return datetime.datetime.utcnow() + datetime.timedelta(minutes=15)


# ── Response helpers ───────────────────────────────────────────────────────────

def ok(data=None, message: str = 'Success', status: int = 200):
    from rest_framework.response import Response
    body: dict = {'success': True, 'message': message}
    if data is not None:
        body['data'] = data
    return Response(body, status=status)


def err(message: str = 'Error', status: int = 400):
    from rest_framework.response import Response
    return Response({'success': False, 'message': message}, status=status)
