
import redis

from app.config import settings
from common_logging import get_logger

logger = get_logger(__name__)
_redis_client: redis.Redis | None = None


def get_redis_client() -> redis.Redis:
    global _redis_client
    if _redis_client is None:
        if settings.REDIS_URL:
            _redis_client = redis.from_url(settings.REDIS_URL, decode_responses=True)
        else:
            _redis_client = redis.Redis(
                host=settings.REDIS_HOST,
                port=settings.REDIS_PORT,
                db=settings.REDIS_DB,
                password=settings.REDIS_PASSWORD,
                decode_responses=True,
            )
    return _redis_client


def record_failed_login(email: str) -> int:
    try:
        client = get_redis_client()
        key = f"failed_login:{email}"
        attempts = client.incr(key)
        if attempts == 1:
            client.expire(key, 900)
        logger.warning(f"Failed login attempt recorded: attempts={attempts}", user_email=email)
        return attempts
    except Exception as e:
        logger.error(f"Redis unavailable for recording failed login: {e}")
        raise RuntimeError("Login security system unavailable. Please try again later.") from None


def is_account_locked(email: str) -> bool:
    try:
        client = get_redis_client()
        key = f"failed_login:{email}"
        attempts = client.get(key)
        if attempts is None:
            return False
        locked = int(attempts) >= 5
        if locked:
            logger.warning(f"Account locked due to failed attempts: {attempts}", user_email=email)
        return locked
    except Exception as e:
        logger.error(f"Redis unavailable for account lock check: {e}")
        raise RuntimeError("Login security system unavailable. Please try again later.") from None


def reset_failed_attempts(email: str) -> None:
    try:
        client = get_redis_client()
        key = f"failed_login:{email}"
        client.delete(key)
        logger.info("Failed login attempts reset", user_email=email)
    except Exception as e:
        logger.error(f"Redis unavailable for resetting failed attempts: {e}")
