"""
Session Manager for FreeExile Edge Gateway.
Maintains active socket connections, latency metrics, and stale session eviction.
"""

import time
import uuid
from typing import Dict, List, Optional
from dataclasses import dataclass, field


@dataclass
class ClientSession:
    session_id: str
    account_id: str
    entity_id: int
    client_ip: str
    connected_timestamp: float = field(default_factory=time.time)
    last_heartbeat_timestamp: float = field(default_factory=time.time)
    last_latency_ms: float = 0.0
    is_authenticated: bool = False


class SessionManager:
    def __init__(self, session_timeout_seconds: float = 30.0):
        self.session_timeout_seconds = session_timeout_seconds
        self.sessions: Dict[str, ClientSession] = {}
        self.entity_to_session: Dict[int, str] = {}

    def create_session(self, account_id: str, entity_id: int, client_ip: str) -> ClientSession:
        session_id = f"sess_{uuid.uuid4().hex[:16]}"
        session = ClientSession(
            session_id=session_id,
            account_id=account_id,
            entity_id=entity_id,
            client_ip=client_ip
        )
        self.sessions[session_id] = session
        self.entity_to_session[entity_id] = session_id
        return session

    def get_session(self, session_id: str) -> Optional[ClientSession]:
        return self.sessions.get(session_id)

    def record_heartbeat(self, session_id: str, latency_ms: float) -> bool:
        session = self.sessions.get(session_id)
        if not session:
            return False
        session.last_heartbeat_timestamp = time.time()
        session.last_latency_ms = latency_ms
        return True

    def remove_session(self, session_id: str) -> Optional[ClientSession]:
        session = self.sessions.pop(session_id, None)
        if session:
            self.entity_to_session.pop(session.entity_id, None)
        return session

    def evict_stale_sessions(self) -> List[str]:
        now = time.time()
        stale_ids = []
        for session_id, session in list(self.sessions.items()):
            if now - session.last_heartbeat_timestamp > self.session_timeout_seconds:
                stale_ids.append(session_id)
                self.remove_session(session_id)
        return stale_ids
