"""ASV benchmarks for Skill Registry persistence operations.

Measures the performance of:
- SkillModel.from_domain() construction
- SkillModel.to_domain() reconstruction
- SkillRepository CRUD operations (in-memory SQLite)
- SkillRegistryService list operations
"""

from __future__ import annotations

import sys
import uuid
from pathlib import Path

try:
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker

    from cleveragents.domain.models.core.skill import Skill
    from cleveragents.infrastructure.database.models import Base, SkillModel
    from cleveragents.infrastructure.database.repositories import (
        SkillRepository,
    )
except ModuleNotFoundError:
    sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker

    from cleveragents.domain.models.core.skill import Skill
    from cleveragents.infrastructure.database.models import Base, SkillModel
    from cleveragents.infrastructure.database.repositories import (
        SkillRepository,
    )


def _make_skill(name: str = "bench/skill-test") -> Skill:
    """Create a minimal Skill domain object for benchmarks."""
    return Skill(
        name=name,
        description=f"Benchmark skill {name}",
        tool_refs=["local/tool-a", "local/tool-b"],
    )


class SkillModelConstruction:
    """Benchmark SkillModel.from_domain() construction."""

    def setup(self) -> None:
        self.skill = _make_skill()

    def time_from_domain(self) -> None:
        SkillModel.from_domain(self.skill)


class SkillModelReconstruction:
    """Benchmark SkillModel.to_domain() reconstruction."""

    def setup(self) -> None:
        self.model = SkillModel.from_domain(_make_skill())

    def time_to_domain(self) -> None:
        self.model.to_domain()


class SkillRepositoryCRUD:
    """Benchmark SkillRepository CRUD with in-memory SQLite."""

    timeout = 60.0

    def setup(self) -> None:
        self.engine = create_engine("sqlite:///:memory:", echo=False)
        Base.metadata.create_all(self.engine)
        self.factory = sessionmaker(bind=self.engine)
        self.repo = SkillRepository(session_factory=self.factory)

    def teardown(self) -> None:
        self.engine.dispose()

    def time_create_skill(self) -> None:
        skill = _make_skill(f"bench/{uuid.uuid4().hex[:8]}")
        self.repo.create(skill)
        # Commit via the same session-factory the repo uses internally
        session = self.factory()
        try:
            session.commit()
        finally:
            session.close()

    def time_get_skill(self) -> None:
        self.repo.get_by_name("bench/nonexistent")

    def time_list_all(self) -> None:
        self.repo.list_all()

    def time_list_namespace(self) -> None:
        self.repo.list_all(namespace="bench")


class SkillRegistryListPerformance:
    """Benchmark listing performance with many skills."""

    timeout = 120.0

    def setup(self) -> None:
        self.engine = create_engine("sqlite:///:memory:", echo=False)
        Base.metadata.create_all(self.engine)
        self.factory = sessionmaker(bind=self.engine)
        self.repo = SkillRepository(session_factory=self.factory)
        # Insert 100 skills and commit via the same session-factory
        for i in range(100):
            skill = _make_skill(f"bench/skill-{i:04d}")
            self.repo.create(skill)
        session = self.factory()
        try:
            session.commit()
        finally:
            session.close()

    def teardown(self) -> None:
        self.engine.dispose()

    def time_list_100_skills(self) -> None:
        self.repo.list_all()

    def time_list_100_skills_filtered(self) -> None:
        self.repo.list_all(namespace="bench")
