"""Integration tests — verify subsystems work together correctly."""

from __future__ import annotations

import pytest
from pathlib import Path

from vastian.agents.base import AgentConfig, BaseAgent, AgentState
from vastian.agents.registry import AgentRegistry
from vastian.bus import MessageBus
from vastian.knowledge.documents import DocumentStore
from vastian.knowledge.structured import StructuredStore
from vastian.tasks.queue import TaskQueue


class TestAgentRegistryIntegration:
    """Integration: Agent YAML loading + registry queries."""

    def test_all_20_agents_load(self, agents_dir: Path) -> None:
        if not agents_dir.exists():
            pytest.skip("agents/ directory not found")
        reg = AgentRegistry()
        count = reg.load_from_directory(agents_dir)
        assert count == 20

    def test_agent_ids_match_expected(self, agents_dir: Path) -> None:
        if not agents_dir.exists():
            pytest.skip("agents/ directory not found")
        reg = AgentRegistry()
        reg.load_from_directory(agents_dir)
        expected = {
            "charles",
            "dominic",
            "liam",
            "henry",
            "finley",
            "theo",
            "elias",
            "victor",
            "adrian",
            "concord",
            "jake",
            "orion",
            "rowan",
            "arjuna",
            "sage",
            "kiran",
            "maya",
            "noah",
            "maria",
            "felix",
        }
        assert set(reg.agent_ids) == expected

    def test_all_agents_have_titles(self, agents_dir: Path) -> None:
        if not agents_dir.exists():
            pytest.skip("agents/ directory not found")
        reg = AgentRegistry()
        reg.load_from_directory(agents_dir)
        for agent_id in reg.agent_ids:
            cfg = reg.get_config(agent_id)
            assert cfg is not None
            assert cfg.title, f"{agent_id} has no title"

    def test_all_agents_have_owned_documents(self, agents_dir: Path) -> None:
        if not agents_dir.exists():
            pytest.skip("agents/ directory not found")
        reg = AgentRegistry()
        reg.load_from_directory(agents_dir)
        for agent_id in reg.agent_ids:
            cfg = reg.get_config(agent_id)
            assert cfg is not None
            assert len(cfg.owned_documents) > 0, f"{agent_id} has no owned_documents"


class TestAgentDocumentAlignment:
    """Integration: Agent YAMLs must have corresponding document folders."""

    def test_all_agents_have_doc_folders(self, agents_dir: Path, docs_dir: Path) -> None:
        if not agents_dir.exists() or not docs_dir.exists():
            pytest.skip("agents/ or docs/ not found")
        reg = AgentRegistry()
        reg.load_from_directory(agents_dir)
        for agent_id in reg.agent_ids:
            agent_doc_dir = docs_dir / agent_id
            assert agent_doc_dir.exists(), f"Missing docs folder: docs/{agent_id}/"

    def test_owned_documents_exist_on_disk(self, agents_dir: Path, docs_dir: Path) -> None:
        if not agents_dir.exists() or not docs_dir.exists():
            pytest.skip("agents/ or docs/ not found")
        reg = AgentRegistry()
        reg.load_from_directory(agents_dir)
        missing = []
        for agent_id in reg.agent_ids:
            cfg = reg.get_config(agent_id)
            if cfg is None:
                continue
            for doc_name in cfg.owned_documents:
                doc_path = docs_dir / agent_id / doc_name
                if not doc_path.exists():
                    missing.append(f"{agent_id}/{doc_name}")
        # docs/ is user data and may be gitignored; skip if most docs are missing
        if len(missing) > 20:
            pytest.skip(
                "docs/ is user data; many owned_documents missing (expected when gitignored)"
            )
        assert missing == [], f"Missing documents: {missing}"


class TestDocumentStoreWithAgents:
    """Integration: DocumentStore reads real agent documents."""

    def test_read_real_document(self, docs_dir: Path) -> None:
        if not docs_dir.exists():
            pytest.skip("docs/ not found")
        target = docs_dir / "charles" / "command-center-dashboard.md"
        if not target.exists():
            pytest.skip(
                "docs/charles/command-center-dashboard.md not found (user data may be gitignored)"
            )
        ds = DocumentStore(docs_dir=docs_dir)
        ds.initialize()
        content = ds.read("charles/command-center-dashboard.md")
        assert "not found" not in content.lower()
        assert len(content) > 50


class TestTaskQueueWithFeed:
    """Integration: TaskQueue data appears in feed API."""

    def test_feed_reads_queue_data(self, temp_dir: Path) -> None:
        from vastian.tasks.feed import NotificationFeed
        import time
        import json
        import urllib.request

        db_path = temp_dir / "tasks.db"
        tq = TaskQueue(db_path)
        tq.initialize()

        # Add some data
        task = tq.enqueue("delegation", "liam", "Integration test task")
        tq.add_notification("liam", "Test notification", "info")

        feed = NotificationFeed(db_path=db_path, port=14560)
        url = feed.start()
        try:
            time.sleep(0.3)
            resp = urllib.request.urlopen(f"{url}/api/notifications", timeout=3)
            data = json.loads(resp.read())
            assert len(data["tasks"]) >= 1
            assert any(t["description"] == "Integration test task" for t in data["tasks"])
            assert len(data["notifications"]) >= 1
        finally:
            feed.stop()
            tq.close()


class TestInboxFolderStructure:
    """Integration: Inbox folder hierarchy exists in data root."""

    def test_inbox_directories_exist(self, data_root: Path) -> None:
        """saved_prompts/inbox, intake, complete live in data root (VASTIAN_DATA_ROOT)."""
        inbox = data_root / "saved_prompts" / "inbox"
        intake = data_root / "saved_prompts" / "intake"
        complete = data_root / "saved_prompts" / "complete"
        if not (data_root / "saved_prompts").exists():
            pytest.skip("saved_prompts not yet seeded (run 'vastian init' to create data root)")
        assert inbox.exists(), "saved_prompts/inbox/ does not exist in data root"
        assert intake.exists(), "saved_prompts/intake/ does not exist in data root"
        assert complete.exists(), "saved_prompts/complete/ does not exist in data root"


class TestAgentBusIntegration:
    """Integration: Agent + MessageBus work together."""

    def test_agent_registers_on_bus(self, agents_dir: Path) -> None:
        if not agents_dir.exists():
            pytest.skip("agents/ not found")
        bus = MessageBus()
        reg = AgentRegistry()
        reg.load_from_directory(agents_dir)

        cfg = reg.get_config("charles")
        assert cfg is not None
        agent = BaseAgent(config=cfg, bus=bus)
        assert "charles" in bus.agent_ids

    def test_agent_builds_system_prompt(self, agents_dir: Path) -> None:
        if not agents_dir.exists():
            pytest.skip("agents/ not found")
        bus = MessageBus()
        reg = AgentRegistry()
        reg.load_from_directory(agents_dir)

        cfg = reg.get_config("liam")
        assert cfg is not None
        agent = BaseAgent(config=cfg, bus=bus)
        prompt = agent.build_system_prompt()
        assert "Liam" in prompt
        assert "TODAY'S DATE" in prompt
