"""ASV benchmarks for skill add persistence (issue #620).

Measures the performance of:
- Adding a skill with DB persistence
- Listing skills after DB-backed add
- Removing a skill with DB persistence
"""

from __future__ import annotations

import importlib
import os
import sys
import tempfile
from pathlib import Path
from typing import Any

# Ensure the local *source* tree is importable even when ASV has an
# older build of the package installed.
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
    sys.path.insert(0, _SRC)

import cleveragents  # noqa: E402

importlib.reload(cleveragents)

from sqlalchemy import create_engine, event  # noqa: E402
from sqlalchemy.orm import Session, sessionmaker  # noqa: E402

from cleveragents.application.services.skill_service import (  # noqa: E402
    SkillService,
)
from cleveragents.infrastructure.database.models import Base  # noqa: E402
from cleveragents.infrastructure.database.repositories import (  # noqa: E402
    SkillRepository,
)
from cleveragents.skills.schema import SkillConfigSchema  # noqa: E402

_VALID_YAML = """\
name: local/bench-persist
description: "Benchmark persistent skill"
tools:
  - name: builtin/read_file
  - name: builtin/write_file
"""


def _enable_fk(dbapi_conn: Any, _rec: Any) -> None:
    cursor = dbapi_conn.cursor()
    cursor.execute("PRAGMA foreign_keys=ON")
    cursor.close()


def _make_service(factory: Any) -> SkillService:
    shared = factory()

    def _sf() -> Session:
        return shared

    repo = SkillRepository(session_factory=_sf)
    return SkillService(skill_repo=repo, session_factory=_sf)


class SkillAddPersistSuite:
    """Benchmark skill add with DB persistence."""

    timeout = 60.0

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

        fd, self._path = tempfile.mkstemp(suffix=".yaml")
        with os.fdopen(fd, "w") as fh:
            fh.write(_VALID_YAML)

    def teardown(self) -> None:
        Path(self._path).unlink(missing_ok=True)
        self.engine.dispose()

    def time_add_persist(self) -> None:
        """Benchmark add with persistence."""
        svc = _make_service(self.factory)
        config = SkillConfigSchema.from_yaml_file(self._path)
        svc.add_skill(config, config_path=self._path)


class SkillListAfterPersistSuite:
    """Benchmark list after persistent adds."""

    timeout = 60.0

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

        svc = _make_service(self.factory)
        for i in range(20):
            yaml_text = (
                f"name: local/bench-list-{i}\n"
                f'description: "Bench {i}"\n'
                "tools:\n"
                "  - name: builtin/read_file\n"
            )
            fd, path = tempfile.mkstemp(suffix=".yaml")
            with os.fdopen(fd, "w") as fh:
                fh.write(yaml_text)
            config = SkillConfigSchema.from_yaml_file(path)
            svc.add_skill(config, config_path=path)
            Path(path).unlink(missing_ok=True)

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

    def time_list_persisted_skills(self) -> None:
        """Benchmark listing skills from a fresh service."""
        svc = _make_service(self.factory)
        svc.list_skills()
