"""Tests for the chatmap CLI."""

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

import pytest

from statusline.chatmap.cli import cmd_read, cmd_update, _resolve_map_file


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


@pytest.fixture
def chatmap_file(session_base):
    """Create a chatmap.json with sample messages."""
    sd = session_base / "test-session"
    sd.mkdir()
    cm = sd / "chatmap.json"
    data = {
        "messages": [
            {"role": "user", "prefix": "Hello world", "label": "greeting", "description": "Initial greeting"},
            {"role": "asst", "prefix": "Hi there!", "label": "", "description": ""},
            {"role": "user", "prefix": "How are you?", "label": "", "description": ""},
        ],
        "last_index": 1,
        "transcript_path": "/dev/null",
    }
    cm.write_text(json.dumps(data))
    return cm


class TestResolveMapFile:
    def test_finds_by_session_id(self, session_base):
        sd = session_base / "sid-1"
        sd.mkdir()
        cm = sd / "chatmap.json"
        cm.write_text(json.dumps({"messages": []}))

        result = _resolve_map_file("sid-1")
        assert result == cm

    def test_exits_on_missing_session(self, session_base):
        with pytest.raises(SystemExit):
            _resolve_map_file("nonexistent")

    def test_exits_on_no_chatmaps(self, session_base):
        with pytest.raises(SystemExit):
            _resolve_map_file()


class _Args:
    """Simple namespace for test args."""
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)


class TestCmdRead:
    def test_shows_new_messages(self, chatmap_file, capsys):
        args = _Args(session_id=None)
        cmd_read(args)
        captured = capsys.readouterr()
        # last_index=1, so messages 2 and 3 should show
        assert "Hi there!" in captured.out
        assert "How are you?" in captured.out
        # Message 1 (greeting) should NOT show — it's before the checkpoint
        assert "Hello world" not in captured.out

    def test_shows_no_new_messages(self, session_base, capsys):
        sd = session_base / "empty-session"
        sd.mkdir()
        cm = sd / "chatmap.json"
        cm.write_text(json.dumps({
            "messages": [{"role": "user", "prefix": "test", "label": "", "description": ""}],
            "last_index": 1,
        }))

        args = _Args(session_id=None)
        cmd_read(args)
        captured = capsys.readouterr()
        assert "no new messages" in captured.out


class TestCmdUpdate:
    def test_sets_checkpoint(self, chatmap_file, capsys):
        args = _Args(session_id=None, id=None, label=None, description=None)
        cmd_update(args)

        data = json.loads(chatmap_file.read_text())
        assert data["last_index"] == 3  # 3 messages

        captured = capsys.readouterr()
        assert "Checkpoint set to 3" in captured.out

    def test_labels_message(self, chatmap_file, capsys):
        args = _Args(session_id=None, id=2, label="response", description="Bot response")
        cmd_update(args)

        data = json.loads(chatmap_file.read_text())
        msg = data["messages"][1]  # 0-indexed
        assert msg["label"] == "response"
        assert msg["description"] == "Bot response"

    def test_partial_update_label_only(self, chatmap_file, capsys):
        args = _Args(session_id=None, id=3, label="followup", description=None)
        cmd_update(args)

        data = json.loads(chatmap_file.read_text())
        msg = data["messages"][2]
        assert msg["label"] == "followup"
        assert msg["description"] == ""  # unchanged

    def test_invalid_message_id(self, chatmap_file):
        args = _Args(session_id=None, id=99, label="x", description=None)
        with pytest.raises(SystemExit):
            cmd_update(args)

    def test_converts_legacy_string_message(self, session_base, capsys):
        sd = session_base / "legacy"
        sd.mkdir()
        cm = sd / "chatmap.json"
        cm.write_text(json.dumps({
            "messages": ["old string message"],
            "last_index": 0,
        }))

        args = _Args(session_id=None, id=1, label="legacy", description="converted")
        cmd_update(args)

        data = json.loads(cm.read_text())
        msg = data["messages"][0]
        assert isinstance(msg, dict)
        assert msg["label"] == "legacy"
        assert msg["prefix"] == "old string message"
