"""Tests for session metadata and chatmap discovery."""

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

import pytest

from statusline.discovery import discover_chatmap, find_session_metadata


@pytest.fixture
def session_base(tmp_path):
    """Create a temporary session base directory and patch SESSION_BASE."""
    base = tmp_path / "claude-sessions"
    base.mkdir()
    with patch("statusline.discovery.SESSION_BASE", base):
        yield base


class TestFindSessionMetadata:
    def test_finds_metadata(self, session_base):
        sd = session_base / "session-1"
        sd.mkdir()
        meta = {"session_id": "session-1", "transcript_path": "/tmp/t.jsonl"}
        (sd / "metadata.json").write_text(json.dumps(meta))

        result = find_session_metadata()
        assert result is not None
        assert result["session_id"] == "session-1"

    def test_filters_by_expected_dir(self, session_base):
        sd = session_base / "session-2"
        sd.mkdir()
        meta = {"session_id": "s2", "transcript_path": "/other/dir/t.jsonl"}
        (sd / "metadata.json").write_text(json.dumps(meta))

        # Should not match — transcript is in /other/dir
        result = find_session_metadata(expected_dir=Path("/expected/dir"))
        assert result is None

    def test_filters_by_exclude_paths(self, session_base):
        sd = session_base / "session-3"
        sd.mkdir()
        tp = Path("/projects/t.jsonl")
        meta = {"session_id": "s3", "transcript_path": str(tp)}
        (sd / "metadata.json").write_text(json.dumps(meta))

        result = find_session_metadata(exclude_paths={tp})
        assert result is None

    def test_matches_with_expected_dir(self, session_base):
        sd = session_base / "session-4"
        sd.mkdir()
        expected = Path("/projects")
        tp = expected / "t.jsonl"
        meta = {"session_id": "s4", "transcript_path": str(tp)}
        (sd / "metadata.json").write_text(json.dumps(meta))

        result = find_session_metadata(expected_dir=expected)
        assert result is not None
        assert result["session_id"] == "s4"

    def test_returns_none_when_no_sessions(self, session_base):
        assert find_session_metadata() is None

    def test_skips_empty_metadata(self, session_base):
        sd = session_base / "session-5"
        sd.mkdir()
        (sd / "metadata.json").write_text(json.dumps({}))

        assert find_session_metadata() is None

    def test_skips_corrupt_json(self, session_base):
        sd = session_base / "session-6"
        sd.mkdir()
        (sd / "metadata.json").write_text("not json")

        assert find_session_metadata() is None


class TestDiscoverChatmap:
    def test_discovers_by_session_id(self, session_base):
        sd = session_base / "my-session"
        sd.mkdir()
        cm = sd / "chatmap.json"
        cm.write_text(json.dumps({"messages": []}))

        result = discover_chatmap("my-session")
        assert result == cm

    def test_returns_none_for_missing_session(self, session_base):
        assert discover_chatmap("nonexistent") is None

    def test_discovers_most_recent(self, session_base):
        # Create two sessions
        sd1 = session_base / "old-session"
        sd1.mkdir()
        cm1 = sd1 / "chatmap.json"
        cm1.write_text(json.dumps({"messages": []}))

        # Ensure different mtime
        time.sleep(0.05)

        sd2 = session_base / "new-session"
        sd2.mkdir()
        cm2 = sd2 / "chatmap.json"
        cm2.write_text(json.dumps({"messages": [{"role": "user"}]}))

        result = discover_chatmap()
        assert result == cm2

    def test_returns_none_when_no_chatmaps(self, session_base):
        assert discover_chatmap() is None

    def test_returns_none_when_no_session_base(self, tmp_path):
        with patch("statusline.discovery.SESSION_BASE", tmp_path / "nope"):
            assert discover_chatmap() is None
