"""
Kodara MCP Server — unit tests.

Tests do NOT require a running MCP client/server.
They exercise format helpers and module-level flags directly.

Run: pytest tests/test_mcp_server.py -v
"""

from __future__ import annotations

import time
import textwrap
from pathlib import Path

import pytest

# ── Helpers to build a minimal KodaraIndex ─────────────────────────────────────


def _make_index(tmp_path: Path):
    """Return a minimal KodaraIndex for testing."""
    from kodara.memory.store import KodaraIndex, INDEX_VERSION, MemoryStore
    from kodara.indexer.scanner import RepositoryScanner
    from kodara.graph.dependency import DependencyGraph

    # Write a minimal Python project
    (tmp_path / "core").mkdir()
    (tmp_path / "core" / "engine.py").write_text(textwrap.dedent("""
        class Engine:
            def run(self): pass
            def stop(self): pass
    """))
    (tmp_path / "utils.py").write_text(textwrap.dedent("""
        from core.engine import Engine

        def helper():
            return Engine()
    """))

    scanner = RepositoryScanner(tmp_path)
    scan = scanner.scan()

    graph = DependencyGraph()
    graph.build(scan)
    graph_data = graph.to_dict()

    modules = {}
    for path, info in scan.files.items():
        modules[path] = {
            "path": path,
            "module_name": Path(path).stem,
            "language": info.language,
            "classes": info.classes,
            "functions": info.functions,
            "exports": info.exports,
            "imports": info.imports,
            "file_hash": info.hash,
            "summary": f"Module {Path(path).stem}",
            "dependencies": graph.get_dependencies(path),
            "dependents": graph.get_dependents(path),
        }

    return KodaraIndex(
        repo_id=MemoryStore.repo_id_from_path(tmp_path),
        display_name="test-project",
        source_root=str(tmp_path),
        indexed_at=time.time(),
        index_version=INDEX_VERSION,
        file_count=len(scan.files),
        language_counts=scan.languages,
        modules=modules,
        graph_edges=graph_data["edges"],
        file_hashes={p: f.hash for p, f in scan.files.items()},
    )


# ── Test 1: import works without crashing ─────────────────────────────────────


def test_mcp_module_importable():
    from kodara.mcp import server  # noqa: F401
    assert True


# ── Test 2: HAS_MCP flag exists and is bool ───────────────────────────────────


def test_has_mcp_flag_exists():
    from kodara.mcp.server import HAS_MCP
    assert isinstance(HAS_MCP, bool)


# ── Test 3: run_server is an async function ───────────────────────────────────


def test_run_server_exists():
    import asyncio
    from kodara.mcp.server import run_server
    assert asyncio.iscoroutinefunction(run_server)


# ── Test 4: _format_ask_result with real index ────────────────────────────────


def test_format_ask_with_index(tmp_path):
    from kodara.mcp.server import _format_ask_result

    index = _make_index(tmp_path)
    result = _format_ask_result(index, "engine run method")
    assert isinstance(result, str)
    assert len(result) > 0


# ── Test 5: _format_ask_result without index → graceful ──────────────────────


def test_format_ask_no_index(tmp_path):
    """When index is None the server returns the not-indexed sentinel."""
    from kodara.mcp.server import _NOT_INDEXED

    # Simulate the server logic when index is None
    index = None
    text = _NOT_INDEXED if index is None else "should not reach"
    assert "not indexed" in text.lower() or "kodara init" in text


# ── Test 6: _format_status with real index → correct data ────────────────────


def test_format_status_with_index(tmp_path):
    from kodara.mcp.server import _format_status

    index = _make_index(tmp_path)
    result = _format_status(index)
    assert isinstance(result, str)
    assert "test-project" in result
    assert "Files" in result or "files" in result.lower()


# ── Test 7: _format_status without index → graceful via sentinel ─────────────


def test_format_status_no_index(tmp_path):
    from kodara.memory.store import MemoryStore
    from kodara.mcp.server import _NOT_INDEXED

    store = MemoryStore(tmp_path)
    index = store.load()  # returns None — nothing indexed
    text = _NOT_INDEXED if index is None else _format_status_call(index)
    assert "not indexed" in text.lower() or "kodara init" in text


def _format_status_call(index):
    from kodara.mcp.server import _format_status
    return _format_status(index)


# ── Test 8: _format_search returns ranked results ────────────────────────────


def test_format_search_with_index(tmp_path):
    from kodara.mcp.server import _format_search

    index = _make_index(tmp_path)
    result = _format_search(index, "engine")
    assert isinstance(result, str)
    assert "engine" in result.lower() or "Search" in result


# ── Test 9: _format_impact with valid file ────────────────────────────────────


def test_format_impact_with_index(tmp_path):
    from kodara.mcp.server import _format_impact

    index = _make_index(tmp_path)
    # Pick a real path from the index
    some_path = list(index.modules.keys())[0]
    result = _format_impact(index, some_path)
    assert isinstance(result, str)
    # Should contain either an impact analysis or a "not found" message
    assert len(result) > 0


# ── Test 10: _format_impact with unknown file → graceful ─────────────────────


def test_format_impact_unknown_file(tmp_path):
    from kodara.mcp.server import _format_impact

    index = _make_index(tmp_path)
    result = _format_impact(index, "does_not_exist.py")
    assert isinstance(result, str)
    assert "not found" in result.lower() or "error" in result.lower() or len(result) > 0


# ── Test 11: _format_context returns architecture text ───────────────────────


def test_format_context_with_index(tmp_path):
    from kodara.mcp.server import _format_context

    index = _make_index(tmp_path)
    result = _format_context(index)
    assert isinstance(result, str)
    assert len(result) > 0


# ── Test 12: regression — existing modules not broken ─────────────────────────


def test_existing_imports_unaffected():
    from kodara.memory.store import MemoryStore  # noqa: F401
    from kodara.engine_client import query_context, query_impact  # noqa: F401
    assert True
