"""Robot Framework helper for repo indexing CLI integration tests.

Provides end-to-end test scenarios that exercise the RepoIndexingService
and CLI wiring together, using an in-memory SQLite database.
"""

from __future__ import annotations

import tempfile
from pathlib import Path

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from cleveragents.application.services.repo_indexing_service import (
    RepoIndexingService,
)
from cleveragents.application.services.resource_registry_service import (
    ResourceRegistryService,
)
from cleveragents.infrastructure.database.models import Base


def _make_services() -> tuple[ResourceRegistryService, RepoIndexingService]:
    """Create fresh services backed by an in-memory database."""
    engine = create_engine("sqlite:///:memory:", echo=False)
    Base.metadata.create_all(engine)
    factory = sessionmaker(bind=engine, expire_on_commit=False)
    resource_svc = ResourceRegistryService(session_factory=factory)
    resource_svc.bootstrap_builtin_types()
    indexing_svc = RepoIndexingService(session_factory=factory)
    return resource_svc, indexing_svc


def test_e2e_add_index_status() -> str:
    """End-to-end: add resource -> index -> check status."""
    resource_svc, indexing_svc = _make_services()

    # Create a temp directory with sample files
    tmp_dir = tempfile.mkdtemp()
    readme = Path(tmp_dir) / "README.md"
    readme.write_text("# Test\nSample content.\n")
    main_py = Path(tmp_dir) / "main.py"
    main_py.write_text("print('hello')\n")

    # Register resource
    resource = resource_svc.register_resource(
        type_name="git-checkout",
        name="local/e2e-repo",
        location=tmp_dir,
        properties={"path": tmp_dir},
    )

    # Index
    repo_index = indexing_svc.index_resource(resource.resource_id, tmp_dir)
    assert repo_index.metadata.status.value == "ready"
    assert repo_index.metadata.file_count >= 2

    # Check status
    status = indexing_svc.get_index_status(resource.resource_id)
    assert status is not None
    assert status.status.value == "ready"
    assert status.file_count == repo_index.metadata.file_count

    return "E2E add-index-status PASSED"


def test_incremental_reindex_after_change() -> str:
    """Incremental re-index after file change."""
    resource_svc, indexing_svc = _make_services()

    tmp_dir = tempfile.mkdtemp()
    readme = Path(tmp_dir) / "README.md"
    readme.write_text("# Original\n")

    resource = resource_svc.register_resource(
        type_name="git-checkout",
        name="local/incr-repo",
        location=tmp_dir,
        properties={"path": tmp_dir},
    )

    # Initial index
    idx1 = indexing_svc.index_resource(resource.resource_id, tmp_dir)
    count1 = idx1.metadata.file_count

    # Add a new file
    new_file = Path(tmp_dir) / "app.py"
    new_file.write_text("x = 1\n")

    # Incremental refresh
    idx2 = indexing_svc.refresh_index(resource.resource_id, tmp_dir)
    assert idx2.metadata.file_count == count1 + 1
    assert idx2.metadata.status.value == "ready"

    return "Incremental reindex PASSED"


def test_full_reindex() -> str:
    """Full re-index replaces the entire index."""
    resource_svc, indexing_svc = _make_services()

    tmp_dir = tempfile.mkdtemp()
    readme = Path(tmp_dir) / "README.md"
    readme.write_text("# Test\n")

    resource = resource_svc.register_resource(
        type_name="git-checkout",
        name="local/full-repo",
        location=tmp_dir,
        properties={"path": tmp_dir},
    )

    # Initial index
    idx1 = indexing_svc.index_resource(resource.resource_id, tmp_dir)

    # Full re-index
    idx2 = indexing_svc.index_resource(resource.resource_id, tmp_dir)
    assert idx2.metadata.status.value == "ready"
    assert idx2.metadata.file_count == idx1.metadata.file_count

    return "Full reindex PASSED"


def test_status_no_index() -> str:
    """Status returns None when no index exists."""
    resource_svc, indexing_svc = _make_services()

    tmp_dir = tempfile.mkdtemp()

    resource = resource_svc.register_resource(
        type_name="git-checkout",
        name="local/no-index-repo",
        location=tmp_dir,
        properties={"path": tmp_dir},
    )

    status = indexing_svc.get_index_status(resource.resource_id)
    assert status is None

    return "Status no-index PASSED"


def test_remove_index() -> str:
    """Remove index cleans up all data."""
    resource_svc, indexing_svc = _make_services()

    tmp_dir = tempfile.mkdtemp()
    readme = Path(tmp_dir) / "README.md"
    readme.write_text("# Test\n")

    resource = resource_svc.register_resource(
        type_name="git-checkout",
        name="local/remove-repo",
        location=tmp_dir,
        properties={"path": tmp_dir},
    )

    indexing_svc.index_resource(resource.resource_id, tmp_dir)
    assert indexing_svc.get_index_status(resource.resource_id) is not None

    removed = indexing_svc.remove_index(resource.resource_id)
    assert removed is True
    assert indexing_svc.get_index_status(resource.resource_id) is None

    return "Remove index PASSED"


if __name__ == "__main__":
    import sys

    _dispatch = {
        "e2e": test_e2e_add_index_status,
        "incremental": test_incremental_reindex_after_change,
        "full": test_full_reindex,
        "no-index": test_status_no_index,
        "remove": test_remove_index,
    }
    if len(sys.argv) < 2 or sys.argv[1] not in _dispatch:
        # Run all tests
        for fn in _dispatch.values():
            print(fn())
    else:
        print(_dispatch[sys.argv[1]]())
