"""
Workflow Engine

Orchestrates the 7-phase workflow for structured feature development.
"""

from dataclasses import dataclass
from pathlib import Path
from typing import Callable, Optional

from rich.console import Console
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn

from ai_coder.workflow.phases import WorkflowPhase, PhaseResult, PHASE_PROMPTS
from ai_coder.llm.interface import LLMProvider, Message
from ai_coder.tools.base import ToolRegistry, ToolExecutor

console = Console()


@dataclass
class WorkflowState:
    """Current state of the workflow."""
    
    task: str
    current_phase: WorkflowPhase
    phase_results: dict[WorkflowPhase, PhaseResult]
    context: dict  # Accumulated context from phases
    user_responses: dict[WorkflowPhase, str]  # User inputs per phase
    
    @classmethod
    def new(cls, task: str) -> "WorkflowState":
        """Create a new workflow state."""
        return cls(
            task=task,
            current_phase=WorkflowPhase.DISCOVERY,
            phase_results={},
            context={},
            user_responses={},
        )


class WorkflowEngine:
    """
    Orchestrates the 7-phase feature development workflow.
    
    Each phase:
    1. Gets a specific prompt based on the phase
    2. Executes tools as needed
    3. May require user input before proceeding
    4. Stores results for subsequent phases
    """
    
    def __init__(
        self,
        llm: LLMProvider,
        tool_registry: ToolRegistry,
        project_root: Path,
        user_input_callback: Optional[Callable[[str], str]] = None,
    ):
        self.llm = llm
        self.tool_registry = tool_registry
        self.tool_executor = ToolExecutor(tool_registry)
        self.project_root = project_root
        self.user_input_callback = user_input_callback or self._default_input
        
        self.state: Optional[WorkflowState] = None
        self.messages: list[Message] = []

    def _default_input(self, prompt: str) -> str:
        """Default user input handler."""
        console.print(f"\n[bold yellow]{prompt}[/bold yellow]")
        return console.input("[bold]Your response: [/bold]")

    def start(self, task: str) -> bool:
        """
        Start the workflow for a given task.
        
        Returns True if the workflow completed successfully.
        """
        self.state = WorkflowState.new(task)
        self.messages = []
        
        console.print(Panel(
            f"[bold blue]Starting Feature Development Workflow[/bold blue]\n"
            f"Task: {task}",
            border_style="blue",
        ))
        
        # Run through all phases
        for phase in WorkflowPhase:
            self.state.current_phase = phase
            
            console.print(f"\n[bold cyan]{'─' * 60}[/bold cyan]")
            console.print(f"[bold]{phase.display_name}[/bold]")
            console.print(f"[dim]{phase.description}[/dim]")
            console.print(f"[bold cyan]{'─' * 60}[/bold cyan]\n")
            
            result = self._execute_phase(phase)
            self.state.phase_results[phase] = result
            
            if not result.success:
                console.print(f"[red]Phase failed: {result.error}[/red]")
                return False
            
            # Handle user input if required
            if result.requires_user_input and result.user_prompt:
                user_response = self.user_input_callback(result.user_prompt)
                self.state.user_responses[phase] = user_response
                self.state.context[f"{phase.value}_user_response"] = user_response
            
            # Store phase output in context
            self.state.context[f"{phase.value}_output"] = result.output
            self.state.context.update(result.data)
        
        console.print(Panel(
            "[bold green]✅ Workflow Complete![/bold green]",
            border_style="green",
        ))
        return True

    def _execute_phase(self, phase: WorkflowPhase) -> PhaseResult:
        """Execute a single workflow phase."""
        try:
            # Build phase prompt
            prompt_template = PHASE_PROMPTS.get(phase, "")
            prompt = prompt_template.format(
                task=self.state.task,
                **self.state.context,
            )
            
            # Add to conversation
            self.messages.append(Message(role="user", content=prompt))
            
            # Get LLM response
            with Progress(
                SpinnerColumn(),
                TextColumn("[progress.description]{task.description}"),
                console=console,
            ) as progress:
                progress.add_task(f"Executing {phase.display_name}...", total=None)
                
                response = self.llm.complete(self.messages)
            
            output = response.content or ""
            console.print(output)
            
            # Add assistant response to conversation
            self.messages.append(Message(role="assistant", content=output))
            
            # Determine if user input is needed
            requires_input = phase in [
                WorkflowPhase.DISCOVERY,
                WorkflowPhase.QUESTIONS,
                WorkflowPhase.ARCHITECTURE,
                WorkflowPhase.IMPLEMENTATION,
                WorkflowPhase.REVIEW,
            ]
            
            user_prompt = None
            if requires_input:
                if phase == WorkflowPhase.DISCOVERY:
                    user_prompt = "Does this understanding look correct? (yes/no/corrections)"
                elif phase == WorkflowPhase.QUESTIONS:
                    user_prompt = "Please answer the questions above:"
                elif phase == WorkflowPhase.ARCHITECTURE:
                    user_prompt = "Which approach do you prefer? (1/2/3 or describe)"
                elif phase == WorkflowPhase.IMPLEMENTATION:
                    user_prompt = "Proceed with implementation? (yes/no)"
                elif phase == WorkflowPhase.REVIEW:
                    user_prompt = "How should we proceed? (fix/later/proceed)"
            
            return PhaseResult(
                phase=phase,
                success=True,
                output=output,
                requires_user_input=requires_input,
                user_prompt=user_prompt,
            )
            
        except Exception as e:
            return PhaseResult.error_result(phase, str(e))

    def get_phase_summary(self, phase: WorkflowPhase) -> Optional[str]:
        """Get the summary of a completed phase."""
        if self.state and phase in self.state.phase_results:
            return self.state.phase_results[phase].output
        return None
