"""
Skill definition models for SKILL.md validation.

This module provides Pydantic models for defining skills in SKILL.md files with
strict validation. All required fields must be non-empty after whitespace
stripping, and unknown fields are rejected to catch configuration errors early.

Requirements: INT-01 (agent capabilities as skills), INT-02 (skill definitions)
"""

from __future__ import annotations

from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Dict

import yaml
from pydantic import BaseModel, Field, field_validator


class SkillFrontmatter(BaseModel):
    """YAML frontmatter for SKILL.md files (INT-01, INT-02).

    Skills are defined in markdown files with YAML frontmatter that specifies
    the skill's name, description, and tool permissions. This model validates
    the frontmatter structure with strict type checking.

    Example:
        ```yaml
        ---
        name: gsd-rlm-plan-phase
        description: Create executable PLAN.md files for a roadmap phase
        tools:
          read: true
          write: true
          bash: true
        color: "#00FFAA"
        ---
        ```
    """

    model_config = {"extra": "forbid"}  # Fail on unknown fields

    name: str = Field(..., min_length=1, description="Skill name")
    description: str = Field(..., min_length=1, description="Skill description")
    tools: Dict[str, bool] = Field(default_factory=dict, description="Tool permissions")
    color: str = Field(default="#00FFAA", description="Display color")

    @field_validator("name", "description")
    @classmethod
    def validate_required_fields(cls, v: str, info) -> str:
        """Ensure required fields are non-empty after stripping whitespace.

        Args:
            v: The field value to validate
            info: Field validation info

        Returns:
            The stripped value if valid

        Raises:
            ValueError: If the field is empty or contains only whitespace
        """
        if not v or not v.strip():
            raise ValueError(f"{info.field_name} is required and cannot be empty")
        return v.strip()


@dataclass
class SkillDefinition:
    """Complete skill definition from SKILL.md (INT-01, INT-02).

    A skill consists of YAML frontmatter (parsed into SkillFrontmatter)
    and a markdown body containing the skill's workflow, purpose, and
    implementation details.

    Attributes:
        frontmatter: Parsed YAML frontmatter
        content: Markdown body after frontmatter
        path: Original SKILL.md file path

    Example:
        >>> skill = SkillDefinition.from_file(Path("skills/planner/SKILL.md"))
        >>> print(skill.frontmatter.name)
        'gsd-rlm-plan-phase'
        >>> print(skill.content[:50])
        '# Plan Phase Skill\\n\\n<role>\\nYou are a GSD...'
    """

    frontmatter: SkillFrontmatter
    content: str
    path: Path = field(default_factory=lambda: Path("."))

    @classmethod
    def from_file(cls, path: Path) -> SkillDefinition:
        """Load skill from SKILL.md file.

        Reads the file content, parses YAML frontmatter between --- markers,
        and creates a SkillDefinition with validated frontmatter and body.

        Args:
            path: Path to the SKILL.md file

        Returns:
            SkillDefinition instance

        Raises:
            ValueError: If file doesn't start with frontmatter or has invalid format
            FileNotFoundError: If file doesn't exist
            yaml.YAMLError: If YAML parsing fails
            ValidationError: If frontmatter validation fails
        """
        content = path.read_text(encoding="utf-8")

        # Validate frontmatter format
        if not content.startswith("---"):
            raise ValueError(f"SKILL.md must start with YAML frontmatter: {path}")

        # Split frontmatter and body
        parts = content.split("---", 2)
        if len(parts) < 3:
            raise ValueError(
                f"Invalid frontmatter format (missing closing ---): {path}"
            )

        frontmatter_yaml = yaml.safe_load(parts[1])
        if not isinstance(frontmatter_yaml, dict):
            raise ValueError(f"Frontmatter must be a YAML mapping: {path}")

        # Create validated frontmatter
        frontmatter = SkillFrontmatter(**frontmatter_yaml)

        # Extract body content (after closing ---)
        body = parts[2].strip()

        return cls(frontmatter=frontmatter, content=body, path=path)

    def validate(self) -> bool:
        """Validate the skill definition.

        Performs basic validation checks:
        - Frontmatter is valid (already validated by Pydantic)
        - Content is non-empty

        Returns:
            True if valid, False otherwise
        """
        if not self.content or not self.content.strip():
            return False
        return True

    @property
    def name(self) -> str:
        """Get skill name from frontmatter."""
        return self.frontmatter.name

    @property
    def description(self) -> str:
        """Get skill description from frontmatter."""
        return self.frontmatter.description

    @property
    def tools(self) -> Dict[str, bool]:
        """Get tool permissions from frontmatter."""
        return self.frontmatter.tools

    def has_tool(self, tool_name: str) -> bool:
        """Check if a tool is enabled for this skill.

        Args:
            tool_name: Name of the tool to check

        Returns:
            True if tool is explicitly enabled, False otherwise
        """
        return self.tools.get(tool_name, False)
