"""Parser for persona YAML files."""

import yaml
from pathlib import Path
from typing import Union

from domain_vigil.core.models import Persona, DealBreaker, Ability, Severity


class PersonaParser:
    """Parser for persona YAML definitions."""

    @staticmethod
    def parse_file(file_path: Union[str, Path]) -> Persona:
        """Parse a persona from a YAML file.

        Args:
            file_path: Path to the YAML file

        Returns:
            Parsed Persona object

        Raises:
            FileNotFoundError: If file doesn't exist
            ValueError: If YAML is invalid or missing required fields
        """
        file_path = Path(file_path)
        if not file_path.exists():
            raise FileNotFoundError(f"Persona file not found: {file_path}")

        with open(file_path, 'r') as f:
            data = yaml.safe_load(f)

        return PersonaParser.parse_dict(data)

    @staticmethod
    def parse_dict(data: dict) -> Persona:
        """Parse a persona from a dictionary.

        Args:
            data: Dictionary with persona definition

        Returns:
            Parsed Persona object

        Raises:
            ValueError: If data is invalid or missing required fields
        """
        if not isinstance(data, dict):
            raise ValueError("Persona data must be a dictionary")

        if "persona" not in data:
            raise ValueError("Missing required field: 'persona'")

        persona_name = data["persona"]
        description = data.get("description", "")

        # Parse deal-breakers
        deal_breakers = []
        for db_data in data.get("deal_breakers", []):
            if not isinstance(db_data, dict):
                raise ValueError(f"Deal-breaker must be a dictionary: {db_data}")

            if "id" not in db_data:
                raise ValueError("Deal-breaker missing required field: 'id'")
            if "description" not in db_data:
                raise ValueError(f"Deal-breaker '{db_data['id']}' missing required field: 'description'")

            severity_str = db_data.get("severity", "critical")
            try:
                severity = Severity(severity_str)
            except ValueError:
                raise ValueError(f"Invalid severity: {severity_str}")

            deal_breaker = DealBreaker(
                id=db_data["id"],
                description=db_data["description"],
                severity=severity,
                examples=db_data.get("examples", []),
                learned_patterns=db_data.get("learned_patterns", [])
            )
            deal_breakers.append(deal_breaker)

        # Parse abilities
        abilities = []
        for ab_data in data.get("abilities", []):
            if not isinstance(ab_data, dict):
                raise ValueError(f"Ability must be a dictionary: {ab_data}")

            if "id" not in ab_data:
                raise ValueError("Ability missing required field: 'id'")
            if "description" not in ab_data:
                raise ValueError(f"Ability '{ab_data['id']}' missing required field: 'description'")

            ability = Ability(
                id=ab_data["id"],
                description=ab_data["description"],
                examples=ab_data.get("examples", [])
            )
            abilities.append(ability)

        metadata = data.get("metadata", {})

        return Persona(
            name=persona_name,
            description=description,
            deal_breakers=deal_breakers,
            abilities=abilities,
            metadata=metadata
        )

    @staticmethod
    def to_dict(persona: Persona) -> dict:
        """Convert a Persona object to a dictionary.

        Args:
            persona: Persona object to convert

        Returns:
            Dictionary representation
        """
        return {
            "persona": persona.name,
            "description": persona.description,
            "deal_breakers": [
                {
                    "id": db.id,
                    "description": db.description,
                    "severity": db.severity.value,
                    "examples": db.examples,
                    "learned_patterns": db.learned_patterns
                }
                for db in persona.deal_breakers
            ],
            "abilities": [
                {
                    "id": ab.id,
                    "description": ab.description,
                    "examples": ab.examples
                }
                for ab in persona.abilities
            ],
            "metadata": persona.metadata
        }

    @staticmethod
    def to_yaml(persona: Persona) -> str:
        """Convert a Persona object to YAML string.

        Args:
            persona: Persona object to convert

        Returns:
            YAML string
        """
        data = PersonaParser.to_dict(persona)
        return yaml.dump(data, default_flow_style=False, sort_keys=False)
