"""Tests for storage module."""

import tempfile
from pathlib import Path

import pytest

from ccontext_mcp.schema import Note, Reference, Step, StepStatus, Task, TaskStatus
from ccontext_mcp.storage import ContextStorage


@pytest.fixture
def temp_dir():
    """Create a temporary directory for tests."""
    with tempfile.TemporaryDirectory() as tmpdir:
        yield Path(tmpdir)


@pytest.fixture
def storage(temp_dir):
    """Create a storage instance with temp directory."""
    return ContextStorage(temp_dir)


class TestContextStorage:
    """Tests for context storage operations."""

    def test_load_empty_context(self, storage):
        """Test loading context when file doesn't exist."""
        context = storage.load_context()
        assert context.version == "1"
        assert context.goal is None
        assert context.why is None
        assert context.agents == {}
        assert context.notes == []
        assert context.references == []

    def test_save_and_load_context(self, storage):
        """Test saving and loading context."""
        context = storage.load_context()
        context.goal = "Test goal"
        context.why = "Test rationale"
        context.agents = {"PeerA": "Working on task"}
        context.notes.append(Note(id="N001", score=50, content="Test note"))
        context.references.append(Reference(id="R001", score=30, uri="test.py", note="Test ref"))
        
        storage.save_context(context)
        
        loaded = storage.load_context()
        assert loaded.goal == "Test goal"
        assert loaded.why == "Test rationale"
        assert loaded.agents == {"PeerA": "Working on task"}
        assert len(loaded.notes) == 1
        assert loaded.notes[0].id == "N001"
        assert loaded.notes[0].score == 50
        assert len(loaded.references) == 1
        assert loaded.references[0].id == "R001"


class TestTaskStorage:
    """Tests for task storage operations."""

    def test_generate_task_id_empty(self, storage):
        """Test generating task ID when no tasks exist."""
        task_id = storage.generate_task_id()
        assert task_id == "T001"

    def test_generate_task_id_increments(self, storage):
        """Test task ID increments correctly."""
        task = Task(
            id="T001",
            name="Test",
            goal="Test",
            steps=[Step(id="S1", name="Step", done="Done", status=StepStatus.PENDING)]
        )
        storage.save_task(task)
        
        next_id = storage.generate_task_id()
        assert next_id == "T002"

    def test_save_and_load_task(self, storage):
        """Test saving and loading a task."""
        task = Task(
            id="T001",
            name="Test Task",
            goal="Complete something",
            status=TaskStatus.ACTIVE,
            assignee="PeerA",
            steps=[
                Step(id="S1", name="Step 1", done="Finish step 1", status=StepStatus.DONE),
                Step(id="S2", name="Step 2", done="Finish step 2", status=StepStatus.IN_PROGRESS),
            ]
        )
        storage.save_task(task)
        
        loaded = storage.load_task("T001")
        assert loaded is not None
        assert loaded.id == "T001"
        assert loaded.name == "Test Task"
        assert loaded.status == TaskStatus.ACTIVE
        assert len(loaded.steps) == 2
        assert loaded.steps[0].status == StepStatus.DONE

    def test_delete_task(self, storage):
        """Test deleting a task."""
        task = Task(
            id="T001",
            name="Test",
            goal="Test",
            steps=[Step(id="S1", name="Step", done="Done", status=StepStatus.PENDING)]
        )
        storage.save_task(task)
        
        assert storage.delete_task("T001") is True
        assert storage.load_task("T001") is None
        assert storage.delete_task("T001") is False

    def test_list_tasks(self, storage):
        """Test listing tasks."""
        for i in range(3):
            task = Task(
                id=f"T{i+1:03d}",
                name=f"Task {i+1}",
                goal="Test",
                steps=[Step(id="S1", name="Step", done="Done", status=StepStatus.PENDING)]
            )
            storage.save_task(task)
        
        tasks = storage.list_tasks()
        assert len(tasks) == 3
        assert tasks[0].id == "T001"
        assert tasks[1].id == "T002"
        assert tasks[2].id == "T003"


class TestScoreDecay:
    """Tests for score decay mechanism."""

    def test_decay_scores(self, storage):
        """Test that scores decay correctly."""
        context = storage.load_context()
        context.notes.append(Note(id="N001", score=10, content="Test"))
        context.references.append(Reference(id="R001", score=5, uri="test.py", note="Test"))
        
        context, archived_notes, archived_refs = storage.decay_scores(context)
        
        assert context.notes[0].score == 9
        assert context.references[0].score == 4
        assert len(archived_notes) == 0
        assert len(archived_refs) == 0

    def test_decay_triggers_archive(self, storage):
        """Test that low scores trigger archiving."""
        context = storage.load_context()
        context.notes.append(Note(id="N001", score=-4, content="Almost archived"))
        context.notes.append(Note(id="N002", score=10, content="Still active"))
        
        context, archived_notes, archived_refs = storage.decay_scores(context)
        
        # N001 should be archived (score becomes -5)
        assert len(archived_notes) == 1
        assert archived_notes[0].id == "N001"
        assert archived_notes[0].score == -5
        
        # N002 should remain
        assert len(context.notes) == 1
        assert context.notes[0].id == "N002"
        assert context.notes[0].score == 9


class TestIDGeneration:
    """Tests for ID generation."""

    def test_generate_note_id(self, storage):
        """Test generating note IDs."""
        context = storage.load_context()
        
        note_id = storage.generate_note_id(context)
        assert note_id == "N001"
        
        context.notes.append(Note(id="N001", score=10, content="Test"))
        note_id = storage.generate_note_id(context)
        assert note_id == "N002"

    def test_generate_reference_id(self, storage):
        """Test generating reference IDs."""
        context = storage.load_context()
        
        ref_id = storage.generate_reference_id(context)
        assert ref_id == "R001"
        
        context.references.append(Reference(id="R001", score=10, uri="test.py", note="Test"))
        ref_id = storage.generate_reference_id(context)
        assert ref_id == "R002"
