"""
Project Planner

Handles the planning phase for new projects, including:
- Task analysis and domain detection
- Agent team composition
- Workspace setup
- Plan presentation
"""

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

from ..intelligence.domain_analyzer import (
    TaskDomain,
    DomainAnalysis,
    analyze_task,
)
from ..agents.templates import (
    AgentTemplate,
    AgentTeamComposition,
    compose_team_for_task,
    get_template,
    list_templates,
)
from .manager import Project, ProjectManager, ProjectAgent


@dataclass
class ProjectPlan:
    """A proposed plan for a new project."""

    # Task analysis
    task_description: str
    domain_analysis: DomainAnalysis

    # Proposed team
    team: AgentTeamComposition

    # Project metadata
    suggested_name: str
    suggested_description: str

    # Approach
    approach_steps: List[str] = field(default_factory=list)
    estimated_complexity: str = "medium"

    # Created project (after approval)
    project: Optional[Project] = None

    @property
    def primary_domain_name(self) -> str:
        """Human-readable primary domain name."""
        return self.domain_analysis.primary_domain.value.replace("_", " ").title()

    @property
    def confidence_level(self) -> str:
        """Human-readable confidence level."""
        conf = self.domain_analysis.primary_confidence
        if conf >= 0.8:
            return "high"
        elif conf >= 0.5:
            return "medium"
        else:
            return "low"


class ProjectPlanner:
    """
    Plans new projects based on user task descriptions.

    The planning flow:
    1. Analyze the task to determine domain(s)
    2. Select appropriate agent templates
    3. Compose a team
    4. Generate an approach/workflow
    5. Present the plan for approval
    6. Create the project if approved
    """

    def __init__(self, manager: ProjectManager):
        """
        Initialize the planner.

        Args:
            manager: ProjectManager instance for creating projects
        """
        self.manager = manager

    def plan_project(self, task_description: str) -> ProjectPlan:
        """
        Create a project plan based on a task description.

        Args:
            task_description: User's task or goal description

        Returns:
            ProjectPlan with analysis and recommended team
        """
        # Step 1: Analyze the task
        analysis = analyze_task(task_description)

        # Step 2: Compose the team
        team = compose_team_for_task(analysis)

        # Step 3: Generate suggested name and description
        suggested_name = self._generate_project_name(task_description, analysis)
        suggested_description = self._generate_description(task_description, analysis)

        # Step 4: Generate approach steps
        approach = self._generate_approach(analysis, team)

        return ProjectPlan(
            task_description=task_description,
            domain_analysis=analysis,
            team=team,
            suggested_name=suggested_name,
            suggested_description=suggested_description,
            approach_steps=approach,
            estimated_complexity=analysis.complexity,
        )

    def execute_plan(
        self,
        plan: ProjectPlan,
        name: Optional[str] = None,
        description: Optional[str] = None,
    ) -> Project:
        """
        Execute a plan by creating the project.

        Args:
            plan: The approved project plan
            name: Override for project name
            description: Override for description

        Returns:
            The created Project
        """
        # Create the project
        project = self.manager.create_project(
            name=name or plan.suggested_name,
            analysis=plan.domain_analysis,
            description=description or plan.suggested_description,
        )

        # Assign the team
        self.manager.assign_team(project.id, plan.team)

        # Store approach as context
        self.manager.set_context(project.id, "approach", plan.approach_steps)
        self.manager.set_context(project.id, "estimated_complexity", plan.estimated_complexity)

        # Complete planning
        self.manager.complete_planning(project.id, {
            "approach": plan.approach_steps,
            "team_size": plan.team.team_size,
            "primary_domain": plan.domain_analysis.primary_domain.value,
        })

        # Update plan with created project
        plan.project = self.manager.get_project(project.id)

        return plan.project

    def format_plan(self, plan: ProjectPlan) -> str:
        """
        Format a plan as human-readable text.

        Args:
            plan: ProjectPlan to format

        Returns:
            Formatted string representation
        """
        lines = [
            "=" * 60,
            "PROJECT PLAN",
            "=" * 60,
            "",
            f"Task: {plan.task_description}",
            "",
            "ANALYSIS",
            "-" * 40,
            f"Domain: {plan.primary_domain_name}",
            f"Confidence: {plan.domain_analysis.primary_confidence:.0%} ({plan.confidence_level})",
            f"Complexity: {plan.estimated_complexity}",
        ]

        # Show secondary domains if any
        if len(plan.domain_analysis.all_domains) > 1:
            secondary = [
                d for d in plan.domain_analysis.all_domains[1:]
                if d.confidence >= 0.4
            ]
            if secondary:
                lines.append("Related domains:")
                for d in secondary:
                    lines.append(f"  - {d.domain.value.replace('_', ' ').title()} ({d.confidence:.0%})")

        lines.extend([
            "",
            "PROPOSED TEAM",
            "-" * 40,
        ])

        # Lead agent
        lines.append(f"Lead: {plan.team.lead.name}")
        lines.append(f"       {plan.team.lead.description}")

        # Specialists
        if plan.team.specialists:
            lines.append("")
            lines.append("Specialists:")
            for agent in plan.team.specialists:
                lines.append(f"  - {agent.name}: {agent.description}")

        # Reviewers
        if plan.team.reviewers:
            lines.append("")
            lines.append("Reviewers:")
            for agent in plan.team.reviewers:
                lines.append(f"  - {agent.name}: {agent.description}")

        lines.extend([
            "",
            "APPROACH",
            "-" * 40,
        ])

        for i, step in enumerate(plan.approach_steps, 1):
            lines.append(f"{i}. {step}")

        lines.extend([
            "",
            "PROJECT DETAILS",
            "-" * 40,
            f"Name: {plan.suggested_name}",
            f"Description: {plan.suggested_description}",
            "",
            "=" * 60,
        ])

        return "\n".join(lines)

    def _generate_project_name(
        self,
        task: str,
        analysis: DomainAnalysis,
    ) -> str:
        """Generate a suggested project name."""
        # Extract key words from task
        words = task.lower().split()

        # Remove common words
        stop_words = {
            "a", "an", "the", "write", "create", "make", "build", "develop",
            "implement", "add", "please", "help", "me", "want", "to", "need",
            "can", "you", "about", "for", "with", "that", "this", "is", "are",
        }
        key_words = [w for w in words if w not in stop_words][:3]

        if key_words:
            name = "-".join(key_words)
        else:
            name = analysis.primary_domain.value.replace("_", "-")

        return name[:50]  # Limit length

    def _generate_description(
        self,
        task: str,
        analysis: DomainAnalysis,
    ) -> str:
        """Generate a project description."""
        domain_name = analysis.primary_domain.value.replace("_", " ")
        return f"{domain_name.title()} project: {task[:150]}"

    def _generate_approach(
        self,
        analysis: DomainAnalysis,
        team: AgentTeamComposition,
    ) -> List[str]:
        """Generate approach steps based on domain and team."""
        domain = analysis.primary_domain

        # Domain-specific approaches
        approaches: Dict[TaskDomain, List[str]] = {
            TaskDomain.CREATIVE_WRITING: [
                "Understand the theme and requirements",
                "Create an outline or structure",
                "Write the first draft",
                "Review and refine",
                "Final polish and editing",
            ],
            TaskDomain.TECHNICAL_CODING: [
                "Analyze requirements and existing code",
                "Design the solution architecture",
                "Implement the core functionality",
                "Write tests",
                "Review and refactor",
            ],
            TaskDomain.DATA_ANALYSIS: [
                "Understand the data and objectives",
                "Explore and clean the data",
                "Perform analysis",
                "Generate visualizations",
                "Document findings and insights",
            ],
            TaskDomain.RESEARCH: [
                "Define research questions",
                "Gather information from multiple sources",
                "Analyze and synthesize findings",
                "Verify and fact-check",
                "Compile report with conclusions",
            ],
            TaskDomain.DOCUMENTATION: [
                "Review the subject matter",
                "Outline the document structure",
                "Write initial content",
                "Add examples and clarifications",
                "Review for clarity and accuracy",
            ],
            TaskDomain.DESIGN_VISUAL: [
                "Understand user needs and context",
                "Create wireframes or mockups",
                "Design the visual elements",
                "Iterate based on feedback",
                "Finalize and document design",
            ],
            TaskDomain.PLANNING: [
                "Gather requirements and constraints",
                "Analyze the problem space",
                "Develop strategic options",
                "Evaluate trade-offs",
                "Create actionable plan",
            ],
            TaskDomain.AUTOMATION: [
                "Identify processes to automate",
                "Design the automation workflow",
                "Implement scripts/pipelines",
                "Test and validate",
                "Document and deploy",
            ],
            TaskDomain.REVIEW_CRITIQUE: [
                "Review the subject material",
                "Identify issues and improvements",
                "Provide detailed feedback",
                "Suggest specific changes",
                "Verify fixes if applicable",
            ],
            TaskDomain.COMMUNICATION: [
                "Understand the audience and purpose",
                "Draft the message/content",
                "Refine tone and clarity",
                "Review for accuracy",
                "Finalize and deliver",
            ],
        }

        # Get approach for domain, or use generic
        approach = approaches.get(domain, [
            "Understand the requirements",
            "Plan the approach",
            "Execute the work",
            "Review and refine",
            "Deliver the result",
        ])

        # Adjust based on complexity
        if analysis.complexity == "simple":
            # Simplify for simple tasks
            approach = approach[:3]
        elif analysis.complexity == "complex":
            # Add review step for complex tasks
            if team.reviewers:
                approach.append(f"Final review by {team.reviewers[0].name}")

        return approach


# Convenience function
def create_project_plan(task_description: str, manager: ProjectManager) -> ProjectPlan:
    """
    Create a project plan for a task.

    Args:
        task_description: User's task description
        manager: ProjectManager instance

    Returns:
        ProjectPlan ready for review
    """
    planner = ProjectPlanner(manager)
    return planner.plan_project(task_description)
