"""ASV benchmarks for Skill Registry flattened tool persistence.

Measures performance of:
- Persisting flattened tools with ``update_flattened_tools``
- Refresh-check via ``needs_refresh``
- Namespace-filtered listing via ``list_all``
"""

from __future__ import annotations

import hashlib
import json
import sys
import uuid
from pathlib import Path

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

    from cleveragents.domain.models.core.skill import Skill
    from cleveragents.infrastructure.database.models import Base
    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 Session, sessionmaker

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


def _make_skill(name: str) -> Skill:
    return Skill(name=name, description=f"Benchmark skill {name}")


class SkillPersistWithTools:
    """Benchmark persisting flattened tools on an existing skill."""

    timeout = 60.0

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

        self.skill = _make_skill("bench/persist-tools")
        self.repo.create(self.skill)
        self.factory().commit()

        self.tools_json = json.dumps([f"tool-{i}" for i in range(20)])
        self.yaml_text = "name: bench/persist-tools\ntools: [...]"
        self.hash_val = hashlib.sha256(self.yaml_text.encode()).hexdigest()

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

    def time_skill_persist_with_tools(self) -> None:
        self.repo.update_flattened_tools(
            name="bench/persist-tools",
            flattened_tools_json=self.tools_json,
            includes_json="[]",
            capability_summary_json="{}",
            yaml_text=self.yaml_text,
            flattening_hash=self.hash_val,
        )
        self.factory().commit()


class SkillRefreshCheck:
    """Benchmark refresh-check (hash comparison)."""

    timeout = 60.0

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

        self.skill = _make_skill("bench/refresh-check")
        self.repo.create(self.skill)
        self.factory().commit()

        self.repo.update_flattened_tools(
            name="bench/refresh-check",
            flattened_tools_json="[]",
            includes_json="[]",
            capability_summary_json="{}",
            yaml_text="name: bench/refresh-check",
            flattening_hash="match_hash",
        )
        self.factory().commit()

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

    def time_skill_refresh_check(self) -> None:
        self.repo.needs_refresh("bench/refresh-check", "match_hash")


class SkillListByNamespace:
    """Benchmark listing skills filtered by namespace."""

    timeout = 60.0

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

        # Seed 50 skills across 5 namespaces
        for ns in ("local", "devops", "data", "ml", "infra"):
            for i in range(10):
                uid = uuid.uuid4().hex[:8]
                self.repo.create(_make_skill(f"{ns}/tool-{i}-{uid}"))
        self.factory().commit()

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

    def time_skill_list_by_namespace(self) -> None:
        self.repo.list_all(namespace="local")
