"""SkillBuilder - Fluent API for constructing Skills.

Accepts both string IDs and typed objects for composition:

    research_pathway = PathwayBuilder("research").tool(...).build()

    skill = (
        SkillBuilder()
        .id("research")
        .name("Research Skill")
        .description("Domain knowledge for research tasks")
        .instructions("Use web.search for queries.")
        .pathway(research_pathway)    # Pathway object or string ID
        .pathway("deep_research")     # String ID also works
        .tag("research", "web")
        .build()
    )
"""

from pathlib import Path
from typing import Self

from core.pathways.pathway import Pathway

# Import from models module to avoid circular dependency with core.skills.skill
from core.skills.models import ScriptToolDeclaration, Skill


class SkillBuilder:
    """Fluent builder for Skill objects.

    Required fields (must be set before build()):
    - id: Unique identifier for the skill
    - name: Human-readable name
    """

    def __init__(self) -> None:
        """Initialize a new skill builder with default values."""
        self._id: str | None = None
        self._name: str | None = None
        self._description: str = ""
        self._instructions: str = ""
        self._pathways: list[str] = []
        self._script_tools: list[ScriptToolDeclaration] = []
        self._scripts_dir: Path | None = None
        self._source_dir: Path | None = None
        self._tags: set[str] = set()
        self._author: str | None = None
        self._version: str | None = None

    def id(self, value: str) -> Self:
        """Set the unique identifier for this skill."""
        self._id = value
        return self

    def name(self, value: str) -> Self:
        """Set the human-readable name."""
        self._name = value
        return self

    def description(self, value: str) -> Self:
        """Set the skill description."""
        self._description = value
        return self

    def instructions(self, value: str) -> Self:
        """Set instructions for how to use this skill."""
        self._instructions = value
        return self

    def pathway(self, *pathways: str | Pathway) -> Self:
        """Add pathways by ID or object.

        Args:
            pathways: Pathway ID strings or built Pathway objects.
        """
        for p in pathways:
            self._pathways.append(p if isinstance(p, str) else p.id)
        return self

    def script_tool(self, tool: ScriptToolDeclaration) -> Self:
        """Add a script tool declaration."""
        self._script_tools.append(tool)
        return self

    def scripts_dir(self, path: Path | str) -> Self:
        """Set the scripts directory for auto-discovery."""
        self._scripts_dir = Path(path) if isinstance(path, str) else path
        return self

    def source_dir(self, path: Path | str) -> Self:
        """Set the source directory for resolving relative paths."""
        self._source_dir = Path(path) if isinstance(path, str) else path
        return self

    def tag(self, *tags: str) -> Self:
        """Add tags for categorization."""
        for t in tags:
            if t:
                self._tags.add(t)
        return self

    def author(self, value: str) -> Self:
        """Set the skill author."""
        self._author = value
        return self

    def version(self, value: str) -> Self:
        """Set the skill version."""
        self._version = value
        return self

    def build(self) -> Skill:
        """Build the Skill object.

        Returns
        -------
            The constructed Skill

        Raises
        ------
            ValueError: If required fields (id, name) are not set
        """
        if not self._id:
            raise ValueError("SkillBuilder.id() is required")
        if not self._name:
            raise ValueError("SkillBuilder.name() is required")

        return Skill(
            id=self._id,
            name=self._name,
            description=self._description,
            instructions=self._instructions,
            pathways=self._pathways,
            script_tools=self._script_tools,
            scripts_dir=self._scripts_dir,
            source_dir=self._source_dir,
            tags=self._tags,
            author=self._author,
            version=self._version,
        )


def skill_builder() -> Self:
    """Create a new skill builder.

    Returns
    -------
        A fresh SkillBuilder instance
    """
    return SkillBuilder()


__all__ = [
    "SkillBuilder",
    "skill_builder",
]
