"""
Enhanced Orchestrator Session Management

Session lifecycle methods extracted from EnhancedTaskOrchestrator.
"""
import structlog
from typing import Optional, Dict, Any

from sessions.session_manager import SessionManager, AgentSession, SessionState
from sessions.heartbeat import HeartbeatMonitor, HeartbeatClient
from brain.context_manager import ContextManager

logger = structlog.get_logger(__name__)


async def create_session(
    session_manager: SessionManager,
    context_manager: ContextManager,
    heartbeat: HeartbeatMonitor,
    voice_sessions: Dict[str, AgentSession],
    heartbeat_clients: Dict[str, HeartbeatClient],
    voice_session_id: str,
    user_id: str = "",
    metadata: Optional[Dict[str, Any]] = None,
    system_prompt: str = "",
) -> AgentSession:
    """Creates a new agent session for a voice session."""
    session = await session_manager.create_session(
        agent_type="voice-orchestrator",
        user_id=user_id,
        context={"voice_session_id": voice_session_id},
        metadata=metadata
    )

    context_manager.create_context(
        session_id=session.session_id,
        system_prompt=system_prompt,
        max_messages=50
    )

    heartbeat_client = HeartbeatClient(
        session_id=session.session_id,
        monitor=heartbeat,
        interval_seconds=10
    )
    await heartbeat_client.start()
    heartbeat.register(session.session_id, "voice-orchestrator")

    voice_sessions[voice_session_id] = session
    heartbeat_clients[session.session_id] = heartbeat_client

    logger.info(
        "Created agent session",
        session_id=session.session_id[:8],
        voice_session_id=voice_session_id
    )
    return session


async def end_session(
    session_manager: SessionManager,
    heartbeat: HeartbeatMonitor,
    voice_sessions: Dict[str, AgentSession],
    heartbeat_clients: Dict[str, HeartbeatClient],
    voice_session_id: str,
) -> None:
    """Ends an agent session."""
    session = voice_sessions.get(voice_session_id)
    if not session:
        return

    if session.session_id in heartbeat_clients:
        await heartbeat_clients[session.session_id].stop()
        del heartbeat_clients[session.session_id]

    heartbeat.unregister(session.session_id)
    session.complete()
    await session_manager.update_session(session)
    del voice_sessions[voice_session_id]

    logger.info(
        "Ended agent session",
        session_id=session.session_id[:8],
        duration_seconds=session.get_duration().total_seconds()
    )


async def recover_session(
    session_manager: SessionManager,
    heartbeat: HeartbeatMonitor,
    voice_sessions: Dict[str, AgentSession],
    heartbeat_clients: Dict[str, HeartbeatClient],
    tasks: Dict[str, Any],
    process_task_fn,
    voice_session_id: str,
    session_id: str,
) -> Optional[AgentSession]:
    """Recovers a session from checkpoint."""
    session = await session_manager.get_session(session_id)

    if not session:
        logger.warning("Session not found for recovery", session_id=session_id)
        return None

    if session.state != SessionState.ACTIVE:
        logger.warning(
            "Session not active for recovery",
            session_id=session_id, state=session.state.value
        )
        return None

    session.resume()

    heartbeat_client = HeartbeatClient(
        session_id=session.session_id,
        monitor=heartbeat,
        interval_seconds=10
    )
    await heartbeat_client.start()
    heartbeat.register(session.session_id, "voice-orchestrator")

    voice_sessions[voice_session_id] = session
    heartbeat_clients[session.session_id] = heartbeat_client

    # Recover pending tasks from checkpoints
    from models.task import TaskState
    for checkpoint in reversed(session.checkpoints):
        if checkpoint.name == "task_queued":
            task_id = checkpoint.data.get("task_id")
            if task_id and task_id in tasks:
                task = tasks[task_id]
                if task.state == TaskState.QUEUED:
                    await process_task_fn(task)
                    logger.info("Recovered pending task", task_id=task_id[:8])

    logger.info(
        "Recovered session",
        session_id=session.session_id[:8],
        checkpoints=len(session.checkpoints)
    )
    return session
