"""Helper script for project CLI Robot Framework integration tests.

Usage: python robot/helper_project_cli.py <test-name>
"""

from __future__ import annotations

import sys

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from cleveragents.application.services.resource_registry_service import (
    ResourceRegistryService,
)
from cleveragents.domain.models.core.project import (
    NamespacedProject,
    parse_namespaced_name,
)
from cleveragents.infrastructure.database.models import Base
from cleveragents.infrastructure.database.repositories import (
    NamespacedProjectRepository,
    ProjectResourceLinkRepository,
)


def _setup_db() -> tuple[
    NamespacedProjectRepository,
    ProjectResourceLinkRepository,
    ResourceRegistryService,
]:
    """Create an in-memory SQLite DB and return repos + service."""
    engine = create_engine("sqlite:///:memory:", echo=False)
    Base.metadata.create_all(engine)
    session = sessionmaker(bind=engine, expire_on_commit=False)()

    class _NoClose:
        def __init__(self, s: object) -> None:
            object.__setattr__(self, "_s", s)

        def close(self) -> None:
            pass

        def __getattr__(self, n: str) -> object:
            return getattr(object.__getattribute__(self, "_s"), n)

    wrapper = _NoClose(session)

    def factory() -> object:
        return wrapper

    proj_repo = NamespacedProjectRepository(session_factory=factory)
    link_repo = ProjectResourceLinkRepository(session_factory=factory)
    svc = ResourceRegistryService(session_factory=factory)
    svc.bootstrap_builtin_types()
    return proj_repo, link_repo, svc


def test_project_crud() -> None:
    """Create, list, show, delete a project."""
    proj_repo, _link_repo, _svc = _setup_db()

    # Create
    parsed = parse_namespaced_name("my-project")
    proj = NamespacedProject(
        name=parsed.name,
        namespace=parsed.namespace,
        description="Robot test project",
    )
    proj_repo.create(proj)

    # List
    projects = proj_repo.list_projects()
    if len(projects) != 1:
        raise AssertionError(f"Expected 1 project, got {len(projects)}")

    # Show
    fetched = proj_repo.get("local/my-project")
    if fetched.namespaced_name != "local/my-project":
        raise AssertionError(f"Name mismatch: {fetched.namespaced_name}")

    # Delete
    deleted = proj_repo.delete("local/my-project")
    if not deleted:
        raise AssertionError("Delete returned False")

    projects_after = proj_repo.list_projects()
    if len(projects_after) != 0:
        raise AssertionError(f"Expected 0 projects, got {len(projects_after)}")

    print("project-crud-ok")


def test_link_lifecycle() -> None:
    """Create project, link resource, unlink, delete."""
    proj_repo, link_repo, svc = _setup_db()

    # Create project
    parsed = parse_namespaced_name("link-test")
    proj = NamespacedProject(
        name=parsed.name,
        namespace=parsed.namespace,
        description="Link test",
    )
    proj_repo.create(proj)

    # Register resource
    res = svc.register_resource(
        type_name="git-checkout",
        name="local/test-repo",
        location="/tmp/test",
        description="Test repo",
    )

    # Link
    link = link_repo.create_link(
        project_name="local/link-test",
        resource_id=res.resource_id,
    )

    # Verify link
    links = link_repo.list_links("local/link-test")
    if len(links) != 1:
        raise AssertionError(f"Expected 1 link, got {len(links)}")

    # Unlink
    link_repo.remove_link(str(link.link_id))
    links_after = link_repo.list_links("local/link-test")
    if len(links_after) != 0:
        raise AssertionError(f"Expected 0 links, got {len(links_after)}")

    # Delete project
    proj_repo.delete("local/link-test")

    print("link-lifecycle-ok")


def test_spec_dict() -> None:
    """Verify _project_spec_dict output keys."""
    from cleveragents.cli.commands.project import _project_spec_dict

    proj_repo, _link_repo, _svc = _setup_db()

    parsed = parse_namespaced_name("dict-test")
    proj = NamespacedProject(
        name=parsed.name,
        namespace=parsed.namespace,
        description="Dict test",
    )
    proj_repo.create(proj)

    fetched = proj_repo.get("local/dict-test")
    data = _project_spec_dict(fetched)
    expected_keys = {
        "namespaced_name",
        "namespace",
        "name",
        "description",
        "linked_resources",
        "created_at",
        "updated_at",
    }
    if set(data.keys()) != expected_keys:
        raise AssertionError(f"Key mismatch: {set(data.keys())} != {expected_keys}")

    print("spec-dict-ok")


TESTS = {
    "project-crud": test_project_crud,
    "link-lifecycle": test_link_lifecycle,
    "spec-dict": test_spec_dict,
}


if __name__ == "__main__":
    if len(sys.argv) < 2 or sys.argv[1] not in TESTS:
        print(f"Usage: {sys.argv[0]} <{'|'.join(TESTS)}>", file=sys.stderr)
        sys.exit(2)
    try:
        TESTS[sys.argv[1]]()
    except Exception as exc:
        print(f"FAIL: {exc}", file=sys.stderr)
        sys.exit(1)
