"""Tests for launcher.session module."""

from __future__ import annotations

import json
import time
from pathlib import Path
from unittest.mock import patch


class TestStartSession:
    """Test session creation."""

    def test_returns_uuid_string(self, tmp_path: Path):
        """Should return a hex UUID string."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import start_session

            session_id = start_session()

        assert isinstance(session_id, str)
        assert len(session_id) == 32  # UUID hex without dashes

    def test_creates_json_file(self, tmp_path: Path):
        """Should create a session JSON file on disk."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import start_session

            session_id = start_session()

        session_file = home / "sessions" / f"{session_id}.json"
        assert session_file.is_file()
        data = json.loads(session_file.read_text())
        assert data["id"] == session_id
        assert data["started_at"] is not None
        assert data["ended_at"] is None

    def test_stores_metadata(self, tmp_path: Path):
        """Should include optional metadata in session record."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import start_session

            session_id = start_session(metadata={"project": "test-app"})

        data = json.loads((home / "sessions" / f"{session_id}.json").read_text())
        assert data["metadata"]["project"] == "test-app"


class TestEndSession:
    """Test session completion."""

    def test_sets_ended_at(self, tmp_path: Path):
        """Should record the end timestamp."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import end_session, start_session

            sid = start_session()
            result = end_session(sid)

        assert result is not None
        assert result["ended_at"] is not None

    def test_computes_duration(self, tmp_path: Path):
        """Should compute duration_seconds."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import end_session, start_session

            sid = start_session()
            result = end_session(sid)

        assert result is not None
        assert result["duration_seconds"] is not None
        assert result["duration_seconds"] >= 0

    def test_returns_none_for_missing_id(self, tmp_path: Path):
        """Should return None when session ID does not exist."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import end_session

            result = end_session("nonexistent_id")

        assert result is None


class TestGetSession:
    """Test session retrieval."""

    def test_loads_by_id(self, tmp_path: Path):
        """Should load and return session record."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import get_session, start_session

            sid = start_session()
            result = get_session(sid)

        assert result is not None
        assert result["id"] == sid

    def test_returns_none_for_missing(self, tmp_path: Path):
        """Should return None for nonexistent session."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import get_session

            result = get_session("does_not_exist")

        assert result is None


class TestListSessions:
    """Test session listing."""

    def test_returns_newest_first(self, tmp_path: Path):
        """Should return sessions ordered newest to oldest."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import list_sessions, start_session

            start_session(metadata={"order": 1})
            time.sleep(0.05)
            sid2 = start_session(metadata={"order": 2})

            result = list_sessions()

        assert len(result) == 2
        assert result[0]["id"] == sid2  # newest first

    def test_respects_limit(self, tmp_path: Path):
        """Should only return up to 'limit' sessions."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import list_sessions, start_session

            for _ in range(5):
                start_session()

            result = list_sessions(limit=2)

        assert len(result) == 2


class TestActiveSession:
    """Test active session detection."""

    def test_returns_non_ended_session(self, tmp_path: Path):
        """Should return a session that hasn't been ended."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import active_session, start_session

            sid = start_session()
            result = active_session()

        assert result is not None
        assert result["id"] == sid

    def test_returns_none_when_all_ended(self, tmp_path: Path):
        """Should return None when all sessions are ended."""
        home = tmp_path / ".tribunal"
        home.mkdir()
        (home / "sessions").mkdir()

        with patch.dict("os.environ", {"SKILLFIELD_HOME": str(home)}):
            from launcher.session import active_session, end_session, start_session

            sid = start_session()
            end_session(sid)
            result = active_session()

        assert result is None
