"""Integration tests for memory system — lifecycle, prompt assembly, init."""

from datetime import date

from fliiq.runtime.agent.prompt import assemble_agent_prompt
from fliiq.runtime.memory.manager import MemoryManager
from fliiq.runtime.memory.retrieval import load_recent_daily, search_memories


def test_skill_memory_lifecycle(tmp_path):
    """Write fitness memory, read, update, search."""
    mgr = MemoryManager(tmp_path / "memory")
    mgr.ensure_dirs()

    # Write
    mgr.save_memory("skills/fitness", "## Fitness\n- Goal: lose 15 lbs\n- Current weight: 180")
    assert mgr.load_memory("skills/fitness") is not None

    # Update
    mgr.save_memory("skills/fitness", "## Fitness\n- Goal: lose 15 lbs\n- Current weight: 175\n- Progress: -5 lbs")
    content = mgr.load_memory("skills/fitness")
    assert "175" in content
    assert "Progress" in content

    # Search
    results = search_memories(mgr, "175")
    assert len(results) == 1
    assert "fitness" in results[0].file_name


def test_prompt_includes_memory_context():
    """Memory context appears after playbook, before clarifications."""
    prompt = assemble_agent_prompt(
        soul="I am Fliiq.",
        playbook="Code carefully.",
        memory_context="### Long-term Memory\nAndy likes sushi.",
        clarifications="Q: What language?\nA: Python",
    )
    # Memory after playbook
    playbook_pos = prompt.index("Code carefully")
    memory_pos = prompt.index("Andy likes sushi")
    clarification_pos = prompt.index("What language")
    assert playbook_pos < memory_pos < clarification_pos


def test_prompt_memory_context_section_header():
    prompt = assemble_agent_prompt(
        soul="I am Fliiq.",
        memory_context="test memory",
    )
    assert "## Memory Context" in prompt
    assert "test memory" in prompt


def test_prompt_without_memory():
    """No memory_context → no Memory Context section."""
    prompt = assemble_agent_prompt(soul="I am Fliiq.")
    assert "Memory Context" not in prompt


def test_full_memory_assembly(tmp_path):
    """MEMORY.md + daily logs + skill list all assembled correctly."""
    mgr = MemoryManager(tmp_path / "memory")
    mgr.ensure_dirs()

    mgr.save_curated("Andy is on Cantonese lesson 20.")
    today = date.today().isoformat()
    mgr.save_memory(today, "Discussed fitness goals today.")
    mgr.save_memory("skills/cantonese", "Lesson history...")
    mgr.save_memory("skills/fitness", "Workout log...")

    # Assemble like _run_agent does
    mem_parts = []
    curated = mgr.load_curated()
    if curated:
        mem_parts.append(f"### Long-term Memory\n{curated}")

    recent = load_recent_daily(mgr, days=3)
    if recent:
        mem_parts.append(f"### Recent Activity\n{recent}")

    skill_memories = mgr.list_skill_memories()
    if skill_memories:
        mem_parts.append(
            "### Available Skill Memories\n"
            + "\n".join(f"- {s}" for s in skill_memories)
        )

    memory_context = "\n\n".join(mem_parts)

    prompt = assemble_agent_prompt(
        soul="I am Fliiq.",
        memory_context=memory_context,
    )

    assert "Cantonese lesson 20" in prompt
    assert "fitness goals today" in prompt
    assert "- cantonese" in prompt
    assert "- fitness" in prompt


def test_init_creates_memory_dirs(tmp_path):
    """MemoryManager.ensure_dirs creates the expected structure."""
    mgr = MemoryManager(tmp_path / ".fliiq" / "memory")
    mgr.ensure_dirs()
    assert (tmp_path / ".fliiq" / "memory").is_dir()
    assert (tmp_path / ".fliiq" / "memory" / "skills").is_dir()
