"""
Per-phone session store backed by Django cache (Redis).
Keeps WhatsApp conversation state across messages with a 30-min TTL.

Session versioning: each session includes a _version field. If the
version doesn't match SESSION_VERSION, the session is treated as stale
and reset on next access.
"""
import json
import logging
from django.core.cache import cache
from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import make_password
import secrets
from django.conf import settings
try:
    import track
except ImportError:
    track = None

logger = logging.getLogger(__name__)

# Initialize Interakt track API key (if provided)
if track:
    track.api_key = getattr(settings, 'INTERAKT_TRACK_KEY', None) or getattr(settings, 'INTERAKT_SECRET_KEY', None)

_PREFIX = "wa_sess:"
SESSION_TTL = 60 * 30  # 30 minutes
SESSION_VERSION = 2     # Bump to invalidate all sessions on deploy

# Message deduplication prefix
_DEDUP_PREFIX = "wa_dedup:"
DEDUP_TTL = 60 * 5  # 5 minutes

User = get_user_model()


def get_session(phone: str) -> dict:
    """Retrieve session for a phone number. Returns empty dict if not found or stale."""
    raw = cache.get(f"{_PREFIX}{phone}")
    if not raw:
        return {}
    try:
        data = json.loads(raw)
    except (json.JSONDecodeError, TypeError):
        return {}
    # Version check — invalidate stale sessions
    if data.get('_version') != SESSION_VERSION:
        clear_session(phone)
        return {}
    return data


def set_session(phone: str, data: dict):
    """Save session data with version stamp."""
    data['_version'] = SESSION_VERSION
    cache.set(f"{_PREFIX}{phone}", json.dumps(data), SESSION_TTL)


def clear_session(phone: str):
    """Delete session for a phone number."""
    cache.delete(f"{_PREFIX}{phone}")


def update_session(phone: str, **kwargs):
    """Merge kwargs into existing session."""
    sess = get_session(phone)
    sess.update(kwargs)
    set_session(phone, sess)


def touch_session(phone: str):
    """Extend session TTL without changing data (keeps conversation alive)."""
    raw = cache.get(f"{_PREFIX}{phone}")
    if raw:
        cache.set(f"{_PREFIX}{phone}", raw, SESSION_TTL)


def is_duplicate_message(message_id: str) -> bool:
    """Check if we've already processed this message (idempotency guard)."""
    if not message_id:
        return False
    key = f"{_DEDUP_PREFIX}{message_id}"
    # Returns True if the key was NOT set (already existed)
    was_set = cache.add(key, "1", DEDUP_TTL)
    return not was_set


def get_or_create_user(phone: str):
    """
    Find or create a User by phone number.
    Cleans the phone to a canonical format (digits only, with country code).
    If creating, generates a secure random password.
    Returns (user, cleaned_phone).
    """
    cleaned = phone.replace('whatsapp:', '').replace('+', '').replace(' ', '').replace('-', '').replace('(', '').replace(')', '').strip()

    # Normalize: ensure 91 prefix for Indian 10-digit numbers
    if len(cleaned) == 10 and cleaned.isdigit():
        cleaned = "91" + cleaned

    # Try multiple phone formats
    user = (
        User.objects.filter(phone=cleaned).first()
        or User.objects.filter(phone=f'+{cleaned}').first()
    )

    # Try without country code
    if not user and cleaned.startswith('91') and len(cleaned) == 12:
        user = (
            User.objects.filter(phone=cleaned[2:]).first()
            or User.objects.filter(phone=f'+{cleaned[2:]}').first()
        )

    # Try by username (legacy bot.py created users with phone as username)
    if not user:
        user = User.objects.filter(username=cleaned).first()

    is_new = False
    generated_password = None
    if not user:
        # Auto-create with insecure password (per user requirement)
        # We use a 8 character random string but could just use something simple
        generated_password = secrets.token_urlsafe(8)[:8]
        user = User.objects.create(
            username=f"wa_{cleaned}",
            phone=cleaned,
            role='CUSTOMER',
            password=make_password(generated_password),
        )
        is_new = True
        logger.info("Auto-created user for WhatsApp number: %s (user_id=%d)", cleaned, user.id)
        
        if track and track.api_key:
            try:
                country_code = "+91" if cleaned.startswith("91") and len(cleaned) == 12 else "+91"
                phone_number = cleaned[2:] if cleaned.startswith("91") and len(cleaned) == 12 else cleaned[-10:]
                track.user(user_id=cleaned, country_code=country_code, phone_number=phone_number, traits={'username': cleaned, 'role': 'CUSTOMER'})
            except Exception as e:
                logger.error(f"Interakt track.user error: {e}")

    return user, cleaned, is_new, generated_password


def format_phone_display(phone: str) -> str:
    """Format phone for display: +91 98765 43210."""
    cleaned = phone.replace('whatsapp:', '').replace('+', '').replace(' ', '').strip()
    if len(cleaned) == 12 and cleaned.startswith('91'):
        return f"+{cleaned[:2]} {cleaned[2:7]} {cleaned[7:]}"
    return phone
