import os
import uuid
from typing import Dict, Any, Optional
import logging

logger = logging.getLogger(__name__)

SESSIONS: Dict[str, Dict[str, Any]] = {}

_USE_REDIS = os.environ.get("CARDISK_USE_REDIS", "").lower() in ("1", "true", "yes")
_redis_client = None
if _USE_REDIS:
    try:
        import redis
        _redis_client = redis.Redis.from_url(os.environ.get("CARDISK_REDIS_URL", "redis://localhost:6379/0"))
    except Exception as e:
        logger.warning("Redis not available: %s", e)
        _redis_client = None
        _USE_REDIS = False

def _redis_set(session_id: str, data: Dict[str, Any]):
    if not _redis_client:
        return
    import json
    _redis_client.set(session_id, json.dumps(data))

def _redis_get(session_id: str):
    if not _redis_client:
        return None
    import json
    v = _redis_client.get(session_id)
    if not v:
        return None
    return json.loads(v)

def new_session(msisdn: str) -> str:
    session_id = str(uuid.uuid4())
    data = {
        "step": "start",
        "data": {"phoneNumber": msisdn}
    }
    if _USE_REDIS:
        _redis_set(session_id, data)
    else:
        SESSIONS[session_id] = data
    logger.debug("Created new session %s for %s", session_id, msisdn)
    return session_id

def get_session_by_id(session_id: str) -> Optional[Dict[str, Any]]:
    if _USE_REDIS:
        return _redis_get(session_id)
    return SESSIONS.get(session_id)

def get_or_create_session(msisdn: str, request_type: int) -> str:
    if int(request_type) == 1:
        return new_session(msisdn)
    if _USE_REDIS and _redis_client:
        for key in _redis_client.scan_iter():
            v = _redis_get(key)
            if v and v.get("data", {}).get("phoneNumber") == msisdn:
                return key.decode() if isinstance(key, bytes) else key
        return new_session(msisdn)
    else:
        for sid, session in reversed(list(SESSIONS.items())):
            if session.get("data", {}).get("phoneNumber") == msisdn:
                return sid
        return new_session(msisdn)

def set_step(session_id: str, step: str):
    logger.debug("Setting session %s step -> %s", session_id, step)
    if _USE_REDIS and _redis_client:
        data = _redis_get(session_id) or {}
        data["step"] = step
        _redis_set(session_id, data)
        return
    if session_id in SESSIONS:
        SESSIONS[session_id]["step"] = step

def get_step(session_id: str) -> str:
    if _USE_REDIS and _redis_client:
        data = _redis_get(session_id) or {}
        return data.get("step", "start")
    return SESSIONS.get(session_id, {}).get("step", "start")

def set_data(session_id: str, key: str, value: Any):
    if _USE_REDIS and _redis_client:
        data = _redis_get(session_id) or {}
        data.setdefault("data", {})[key] = value
        _redis_set(session_id, data)
        return
    if session_id in SESSIONS:
        SESSIONS[session_id]["data"][key] = value
