"""
Agent Development Mode

Provides functionality for creating, testing, and managing custom agent templates.
"""

import yaml
from dataclasses import dataclass, field
from pathlib import Path
from typing import List, Dict, Optional, Any

from .templates.base import (
    AgentTemplate,
    AgentCapability,
    CollaborationStyle,
    AgentRole,
)
from .templates.registry import get_registry, TemplateRegistry
from ..intelligence.domain_analyzer import TaskDomain


@dataclass
class TemplateValidation:
    """Result of validating an agent template."""
    is_valid: bool
    errors: List[str] = field(default_factory=list)
    warnings: List[str] = field(default_factory=list)


@dataclass
class TestResult:
    """Result of testing an agent template."""
    template_id: str
    test_task: str
    success: bool
    output: str = ""
    error: Optional[str] = None
    duration_ms: Optional[int] = None


class AgentDeveloper:
    """
    Tools for developing and managing custom agent templates.

    Features:
    - Interactive template creation
    - Template validation
    - Template testing (sandbox)
    - Import/export to YAML
    """

    def __init__(
        self,
        registry: Optional[TemplateRegistry] = None,
        custom_templates_dir: Optional[Path] = None,
    ):
        """
        Initialize the agent developer.

        Args:
            registry: Template registry (uses global if not provided)
            custom_templates_dir: Directory for storing custom templates
        """
        self.registry = registry or get_registry()
        self.custom_templates_dir = (
            custom_templates_dir or
            Path.home() / ".orchestrator" / "templates"
        )
        self.custom_templates_dir.mkdir(parents=True, exist_ok=True)

    def create_template(
        self,
        id: str,
        name: str,
        description: str,
        domain: TaskDomain,
        system_prompt: str,
        capabilities: Optional[List[Dict[str, Any]]] = None,
        suggested_tools: Optional[List[str]] = None,
        collaboration_style: CollaborationStyle = CollaborationStyle.COLLABORATIVE,
        default_role: AgentRole = AgentRole.SPECIALIST,
        secondary_domains: Optional[List[TaskDomain]] = None,
        tags: Optional[List[str]] = None,
    ) -> AgentTemplate:
        """
        Create a new agent template.

        Args:
            id: Unique template identifier
            name: Display name
            description: Brief description
            domain: Primary task domain
            system_prompt: System prompt for the agent
            capabilities: List of capability dicts
            suggested_tools: List of tool names
            collaboration_style: How the agent works with others
            default_role: Default role in a team
            secondary_domains: Additional domains
            tags: Searchable tags

        Returns:
            The created AgentTemplate
        """
        # Convert capability dicts to AgentCapability objects
        caps = []
        if capabilities:
            for cap in capabilities:
                caps.append(AgentCapability(
                    name=cap["name"],
                    description=cap.get("description", ""),
                    proficiency=cap.get("proficiency", 1.0),
                ))

        template = AgentTemplate(
            id=id,
            name=name,
            description=description,
            domain=domain,
            secondary_domains=secondary_domains or [],
            capabilities=caps,
            suggested_tools=suggested_tools or [],
            collaboration_style=collaboration_style,
            default_role=default_role,
            system_prompt=system_prompt,
            tags=tags or [],
            author="custom",
        )

        return template

    def validate_template(self, template: AgentTemplate) -> TemplateValidation:
        """
        Validate an agent template.

        Args:
            template: Template to validate

        Returns:
            TemplateValidation with errors and warnings
        """
        errors = []
        warnings = []

        # Check required fields
        if not template.id:
            errors.append("Template ID is required")
        elif not template.id.replace("-", "").replace("_", "").isalnum():
            errors.append("Template ID should be alphanumeric with hyphens/underscores only")

        if not template.name:
            errors.append("Template name is required")

        if not template.description:
            warnings.append("Template should have a description")

        if not template.system_prompt:
            errors.append("System prompt is required")
        elif len(template.system_prompt) < 50:
            warnings.append("System prompt seems short - consider adding more detail")

        # Check for duplicate ID
        existing = self.registry.get(template.id)
        if existing and existing.author != "custom":
            errors.append(f"Template ID '{template.id}' conflicts with a built-in template")

        # Check capabilities
        if not template.capabilities:
            warnings.append("Template has no defined capabilities")

        # Validate domain
        try:
            TaskDomain(template.domain.value)
        except ValueError:
            errors.append(f"Invalid domain: {template.domain}")

        return TemplateValidation(
            is_valid=len(errors) == 0,
            errors=errors,
            warnings=warnings,
        )

    def register_template(self, template: AgentTemplate) -> None:
        """
        Register a template in the registry.

        Args:
            template: Template to register

        Raises:
            ValueError: If validation fails
        """
        validation = self.validate_template(template)
        if not validation.is_valid:
            raise ValueError(f"Invalid template: {', '.join(validation.errors)}")

        self.registry.register(template)

    def export_template(
        self,
        template: AgentTemplate,
        file_path: Optional[Path] = None,
    ) -> Path:
        """
        Export a template to YAML file.

        Args:
            template: Template to export
            file_path: Output path (defaults to custom_templates_dir)

        Returns:
            Path to the exported file
        """
        if file_path is None:
            file_path = self.custom_templates_dir / f"{template.id}.yaml"

        data = template.to_dict()

        with open(file_path, "w") as f:
            yaml.dump(data, f, default_flow_style=False, sort_keys=False)

        return file_path

    def import_template(self, file_path: Path) -> AgentTemplate:
        """
        Import a template from YAML file.

        Args:
            file_path: Path to YAML file

        Returns:
            The imported AgentTemplate
        """
        with open(file_path) as f:
            data = yaml.safe_load(f)

        template = AgentTemplate.from_dict(data)
        return template

    def list_custom_templates(self) -> List[AgentTemplate]:
        """
        List all custom templates from the templates directory.

        Returns:
            List of custom AgentTemplates
        """
        templates = []

        for yaml_file in self.custom_templates_dir.glob("*.yaml"):
            try:
                template = self.import_template(yaml_file)
                templates.append(template)
            except Exception:
                continue  # Skip invalid files

        return templates

    def delete_custom_template(self, template_id: str) -> bool:
        """
        Delete a custom template file.

        Args:
            template_id: ID of template to delete

        Returns:
            True if deleted, False if not found
        """
        file_path = self.custom_templates_dir / f"{template_id}.yaml"
        if file_path.exists():
            file_path.unlink()
            return True
        return False

    def generate_template_prompt(
        self,
        name: str,
        domain: str,
        capabilities: List[str],
        style: str = "helpful and professional",
    ) -> str:
        """
        Generate a system prompt for a new agent template.

        Args:
            name: Agent name
            domain: Primary domain
            capabilities: List of capability descriptions
            style: Personality/style description

        Returns:
            Generated system prompt
        """
        caps_text = "\n".join(f"- {cap}" for cap in capabilities)

        return f"""You are {name}, a specialized agent in the {domain} domain.

Your core capabilities include:
{caps_text}

Your communication style is {style}.

When working on tasks:
1. Carefully analyze the requirements
2. Apply your specialized expertise
3. Provide clear, actionable results
4. Explain your reasoning when helpful

You focus on delivering high-quality work within your area of expertise."""

    def format_template_info(self, template: AgentTemplate) -> str:
        """
        Format template information for display.

        Args:
            template: Template to format

        Returns:
            Formatted string
        """
        lines = [
            f"Template: {template.name}",
            f"ID: {template.id}",
            f"Domain: {template.domain.value}",
            f"Author: {template.author}",
            f"Version: {template.version}",
            "",
            f"Description: {template.description}",
            "",
            "Capabilities:",
        ]

        for cap in template.capabilities:
            lines.append(f"  - {cap.name} ({cap.proficiency:.0%})")
            if cap.description:
                lines.append(f"    {cap.description}")

        if template.suggested_tools:
            lines.append("")
            lines.append(f"Tools: {', '.join(template.suggested_tools)}")

        if template.tags:
            lines.append(f"Tags: {', '.join(template.tags)}")

        lines.append("")
        lines.append(f"Collaboration: {template.collaboration_style.value}")
        lines.append(f"Default Role: {template.default_role.value}")

        return "\n".join(lines)


class TemplateWizard:
    """
    Interactive wizard for creating agent templates.

    Guides users through the template creation process.
    """

    def __init__(self, developer: Optional[AgentDeveloper] = None):
        """Initialize the wizard."""
        self.developer = developer or AgentDeveloper()
        self._state: Dict[str, Any] = {}

    def start(self) -> Dict[str, str]:
        """
        Get the first set of questions for the wizard.

        Returns:
            Dict with question keys and prompts
        """
        self._state = {}
        return {
            "id": "Enter a unique ID for this agent (e.g., my-custom-agent):",
            "name": "Enter a display name:",
            "domain": f"Select a domain ({', '.join(d.value for d in TaskDomain)}):",
        }

    def process_step1(
        self,
        id: str,
        name: str,
        domain: str,
    ) -> Dict[str, str]:
        """
        Process step 1 answers and get step 2 questions.

        Returns:
            Dict with question keys and prompts
        """
        self._state["id"] = id
        self._state["name"] = name
        self._state["domain"] = TaskDomain(domain)

        return {
            "description": "Enter a brief description of what this agent does:",
            "capabilities": "List the agent's capabilities (comma-separated):",
        }

    def process_step2(
        self,
        description: str,
        capabilities: str,
    ) -> Dict[str, str]:
        """
        Process step 2 answers and get step 3 questions.

        Returns:
            Dict with question keys and prompts
        """
        self._state["description"] = description
        self._state["capabilities"] = [
            {"name": cap.strip(), "description": "", "proficiency": 1.0}
            for cap in capabilities.split(",")
            if cap.strip()
        ]

        return {
            "style": "Describe the agent's communication style:",
            "tools": "List suggested tools (comma-separated, or leave empty):",
        }

    def process_step3(
        self,
        style: str,
        tools: str,
    ) -> AgentTemplate:
        """
        Process step 3 and create the template.

        Returns:
            The created AgentTemplate
        """
        suggested_tools = [
            t.strip() for t in tools.split(",") if t.strip()
        ]

        # Generate system prompt
        cap_names = [c["name"] for c in self._state["capabilities"]]
        system_prompt = self.developer.generate_template_prompt(
            name=self._state["name"],
            domain=self._state["domain"].value,
            capabilities=cap_names,
            style=style,
        )

        # Create the template
        template = self.developer.create_template(
            id=self._state["id"],
            name=self._state["name"],
            description=self._state["description"],
            domain=self._state["domain"],
            system_prompt=system_prompt,
            capabilities=self._state["capabilities"],
            suggested_tools=suggested_tools,
        )

        return template


# Convenience functions
def create_custom_template(
    id: str,
    name: str,
    description: str,
    domain: TaskDomain,
    system_prompt: str,
    **kwargs,
) -> AgentTemplate:
    """
    Create and register a custom agent template.

    Args:
        id: Template ID
        name: Display name
        description: Brief description
        domain: Primary domain
        system_prompt: System prompt
        **kwargs: Additional template options

    Returns:
        The created and registered template
    """
    developer = AgentDeveloper()
    template = developer.create_template(
        id=id,
        name=name,
        description=description,
        domain=domain,
        system_prompt=system_prompt,
        **kwargs,
    )
    developer.register_template(template)
    return template


def load_custom_templates() -> int:
    """
    Load all custom templates from the templates directory.

    Returns:
        Number of templates loaded
    """
    developer = AgentDeveloper()
    templates = developer.list_custom_templates()

    for template in templates:
        try:
            developer.register_template(template)
        except ValueError:
            continue  # Skip invalid templates

    return len(templates)
