"""Pattern templates and code generators."""

from enum import Enum
from pathlib import Path
from typing import Dict, Optional


class PatternTemplate(str, Enum):
    """Available pattern templates."""

    REFLECTION = "reflection"
    REACT = "react"
    PLANNING = "planning"
    MULTI_AGENT = "multi_agent"
    CUSTOM = "custom"


class TemplateGenerator:
    """Generate pattern boilerplate code."""

    @staticmethod
    def generate_reflection_pattern(
        name: str,
        description: str = "Custom reflection pattern"
    ) -> str:
        """Generate reflection pattern template.

        Args:
            name: Pattern class name
            description: Pattern description

        Returns:
            Generated code
        """
        return f'''"""
{description}
"""

from pygeai_orchestration.patterns.reflection import ReflectionPattern
from pygeai_orchestration.core.base import PatternConfig, PatternResult


class {name}(ReflectionPattern):
    """{description}."""

    async def reflect(self, task: str, result: str, context=None) -> str:
        """Reflect on task and result.

        Args:
            task: Original task
            result: Initial result
            context: Optional context

        Returns:
            Reflection feedback
        """
        reflection_prompt = f"""
        Task: {{task}}
        Result: {{result}}

        Please analyze this result and provide feedback for improvement.
        """

        reflection = await self.agent.generate(reflection_prompt)
        return reflection

    async def improve(self, task: str, result: str, reflection: str, context=None) -> str:
        """Improve result based on reflection.

        Args:
            task: Original task
            result: Initial result
            reflection: Reflection feedback
            context: Optional context

        Returns:
            Improved result
        """
        improvement_prompt = f"""
        Task: {{task}}
        Previous Result: {{result}}
        Reflection: {{reflection}}

        Please provide an improved result based on the reflection.
        """

        improved = await self.agent.generate(improvement_prompt)
        return improved
'''

    @staticmethod
    def generate_react_pattern(
        name: str,
        description: str = "Custom ReAct pattern"
    ) -> str:
        """Generate ReAct pattern template.

        Args:
            name: Pattern class name
            description: Pattern description

        Returns:
            Generated code
        """
        return f'''"""
{description}
"""

from pygeai_orchestration.patterns.react import ReActPattern
from pygeai_orchestration.core.base import PatternConfig, PatternResult


class {name}(ReActPattern):
    """{description}."""

    async def think(self, task: str, context=None) -> str:
        """Reason about the task.

        Args:
            task: Task to think about
            context: Optional context

        Returns:
            Reasoning result
        """
        thought_prompt = f"""
        Task: {{task}}

        Think step by step about how to solve this task.
        """

        thought = await self.agent.generate(thought_prompt)
        return thought

    async def act(self, task: str, thought: str, context=None) -> str:
        """Take action based on reasoning.

        Args:
            task: Original task
            thought: Reasoning result
            context: Optional context

        Returns:
            Action result
        """
        action_prompt = f"""
        Task: {{task}}
        Thought: {{thought}}

        Based on this reasoning, take the appropriate action.
        """

        action = await self.agent.generate(action_prompt)
        return action
'''

    @staticmethod
    def generate_custom_pattern(
        name: str,
        description: str = "Custom orchestration pattern"
    ) -> str:
        """Generate custom pattern template.

        Args:
            name: Pattern class name
            description: Pattern description

        Returns:
            Generated code
        """
        return f'''"""
{description}
"""

from pygeai_orchestration.core.base import OrchestrationPattern, PatternConfig, PatternResult


class {name}(OrchestrationPattern):
    """{description}."""

    async def _execute_impl(self, task: str, context=None) -> PatternResult:
        """Execute pattern implementation.

        Args:
            task: Task to execute
            context: Optional execution context

        Returns:
            Pattern execution result
        """
        # TODO: Implement your pattern logic here

        result = await self.agent.generate(task)

        return PatternResult(
            success=True,
            result=result,
            metadata={{"pattern": "{name}"}}
        )
'''

    @staticmethod
    def generate_test_file(
        pattern_name: str,
        template: PatternTemplate
    ) -> str:
        """Generate test file for pattern.

        Args:
            pattern_name: Pattern class name
            template: Pattern template type

        Returns:
            Generated test code
        """
        return f'''"""
Tests for {pattern_name}.
"""

import unittest
from pygeai_orchestration.dev.testing import MockAgent, PatternTestCase


class Test{pattern_name}(PatternTestCase):
    """Test cases for {pattern_name}."""

    def setUp(self):
        """Set up test fixtures."""
        self.agent = MockAgent()
        # TODO: Initialize your pattern
        # self.pattern = {pattern_name}(self.agent)

    async def test_basic_execution(self):
        """Test basic pattern execution."""
        # TODO: Implement test
        pass

    async def test_error_handling(self):
        """Test error handling."""
        # TODO: Implement test
        pass

    async def test_result_format(self):
        """Test result format."""
        # TODO: Implement test
        pass


if __name__ == "__main__":
    unittest.main()
'''

    @staticmethod
    def save_template(
        code: str,
        output_path: Path,
        overwrite: bool = False
    ) -> None:
        """Save generated template to file.

        Args:
            code: Generated code
            output_path: Output file path
            overwrite: Whether to overwrite existing file

        Raises:
            FileExistsError: If file exists and overwrite is False
        """
        if output_path.exists() and not overwrite:
            raise FileExistsError(f"File already exists: {output_path}")

        output_path.parent.mkdir(parents=True, exist_ok=True)

        with open(output_path, "w") as f:
            f.write(code)

    @classmethod
    def create_pattern(
        cls,
        template: PatternTemplate,
        name: str,
        description: str,
        output_dir: Optional[Path] = None,
        include_tests: bool = True
    ) -> Dict[str, str]:
        """Create complete pattern with optional tests.

        Args:
            template: Pattern template type
            name: Pattern class name
            description: Pattern description
            output_dir: Output directory (optional)
            include_tests: Generate test file

        Returns:
            Dictionary of filename -> code
        """
        files = {}

        if template == PatternTemplate.REFLECTION:
            code = cls.generate_reflection_pattern(name, description)
        elif template == PatternTemplate.REACT:
            code = cls.generate_react_pattern(name, description)
        else:
            code = cls.generate_custom_pattern(name, description)

        pattern_filename = f"{name.lower()}.py"
        files[pattern_filename] = code

        if include_tests:
            test_code = cls.generate_test_file(name, template)
            test_filename = f"test_{name.lower()}.py"
            files[test_filename] = test_code

        if output_dir:
            output_path = Path(output_dir)
            for filename, content in files.items():
                file_path = output_path / filename
                cls.save_template(content, file_path)

        return files
