"""
Orchestrated Workspace - Advanced multi-agent orchestration with task decomposition.

This module provides sophisticated orchestration that breaks tasks into subtasks,
assigns them to specialized agents, and coordinates execution in a collaborative workspace.
"""

import asyncio
import json
import logging
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Optional

from synqed.orchestrator import Orchestrator, OrchestrationResult
from synqed.workspace import Workspace, WorkspaceState

logger = logging.getLogger(__name__)


class CollaborationMode(Enum):
    """Defines how agents interact during collaboration."""
    COLLABORATIVE = "collaborative"  # Supportive, synergy-seeking
    ADVERSARIAL = "adversarial"      # Force conflict, critique, then synthesis
    INDEPENDENT = "independent"       # No interaction between agents


@dataclass
class Subtask:
    """A subtask within a larger task."""
    subtask_id: str
    description: str
    assigned_agent_id: str
    assigned_agent_name: str
    dependencies: list[str] = field(default_factory=list)  # IDs of subtasks this depends on
    order: int = 0
    status: str = "pending"  # pending, in_progress, completed, failed
    result: str | None = None
    metadata: dict[str, Any] = field(default_factory=dict)


@dataclass
class ExecutionPlan:
    """A plan for executing a complex task."""
    plan_id: str
    original_task: str
    subtasks: list[Subtask]
    execution_order: list[list[str]]  # List of parallel execution stages
    selected_agents: list[str]  # Agent IDs needed for this plan
    reasoning: str
    metadata: dict[str, Any] = field(default_factory=dict)


@dataclass
class ExecutionResult:
    """Result of executing an orchestrated plan."""
    plan: ExecutionPlan
    workspace_id: str
    final_result: str
    subtask_results: dict[str, str]  # subtask_id -> result
    success: bool
    workspace_messages: list[dict[str, Any]] = field(default_factory=list)  # All messages from workspace
    error: str | None = None
    metadata: dict[str, Any] = field(default_factory=dict)


class OrchestratedWorkspace:
    """
    Advanced orchestration that breaks tasks into subtasks and coordinates
    execution across specialized agents in a collaborative workspace.
    
    This orchestrator:
    1. Analyzes the user's task
    2. Breaks it into subtasks
    3. Builds an execution plan
    4. Assigns each subtask to the best agent
    5. Creates a temporary workspace
    6. Executes subtasks with agent collaboration
    7. Synthesizes final result
    
    Example:
        ```python
        # Create orchestrated workspace with adversarial collaboration (default)
        orchestrated = OrchestratedWorkspace(
            orchestrator=orchestrator,
            enable_agent_discussion=True,
            collaboration_mode=CollaborationMode.ADVERSARIAL,  # Force conflict → synthesis
            display_messages=True,  # Enable colored message display
        )
        
        # Or use collaborative mode for supportive feedback
        # collaboration_mode=CollaborationMode.COLLABORATIVE
        
        # Or use independent mode for no interaction
        # collaboration_mode=CollaborationMode.INDEPENDENT
        
        # Register agents
        orchestrated.register_agent(research_agent)
        orchestrated.register_agent(coding_agent)
        orchestrated.register_agent(writing_agent)
        
        # Execute complex task
        result = await orchestrated.execute_task(
            "Research microservices patterns, write implementation code, "
            "and create documentation"
        )
        
        print(f"Success: {result.success}")
        print(f"Result: {result.final_result}")
        ```
    """
    
    def __init__(
        self,
        orchestrator: Orchestrator,
        enable_agent_discussion: bool = True,
        collaboration_mode: CollaborationMode = CollaborationMode.ADVERSARIAL,
        workspace_persistence: bool = False,
        max_parallel_subtasks: int = 3,
        message_callback: Optional[Any] = None,
        display_messages: bool = False,  # Enable built-in colored message display
        display_verbose: bool = False,   # Show full message details
    ):
        """
        Initialize the orchestrated workspace.
        
        Args:
            orchestrator: Orchestrator instance for LLM-based planning
            enable_agent_discussion: Whether agents can discuss in workspace
            collaboration_mode: How agents interact (ADVERSARIAL, COLLABORATIVE, or INDEPENDENT)
            workspace_persistence: Whether to persist workspace state
            max_parallel_subtasks: Maximum subtasks to run in parallel
            message_callback: Optional custom callback function(msg_dict) for real-time messages
            display_messages: Enable built-in colored message display (default: False)
            display_verbose: Show full message details including type and phase (default: False)
        """
        self.orchestrator = orchestrator
        self.enable_agent_discussion = enable_agent_discussion
        self.collaboration_mode = collaboration_mode
        self.workspace_persistence = workspace_persistence
        self.max_parallel_subtasks = max_parallel_subtasks
        self.display_verbose = display_verbose
        
        # Setup message callback
        if display_messages:
            # Create a simple display callback without colored output
            def display_callback(msg_dict):
                # Print with simple output
                sender = msg_dict.get('sender_name', 'System')
                content = msg_dict.get('content', '')
                print(f"[{sender}] {content}")
                
                # Call custom callback if provided
                if message_callback:
                    message_callback(msg_dict)
            
            self.message_callback = display_callback
        else:
            self.message_callback = message_callback
        
        # Track agents
        self._agents: dict[str, Any] = {}  # agent_id -> agent
        
        logger.info("OrchestratedWorkspace initialized")
    
    def register_agent(self, agent: Any) -> None:
        """
        Register an agent for orchestration.
        
        Args:
            agent: Agent instance to register
        """
        agent_id = agent.name
        self._agents[agent_id] = agent
        
        # Register with orchestrator
        self.orchestrator.register_agent(
            agent_card=agent.card,
            agent_url=agent.url,
            agent_id=agent_id,
        )
        
        logger.info(f"Registered agent: {agent_id}")
    
    async def execute_task(
        self,
        task: str,
        context: dict[str, Any] | None = None,
        workspace_name: str | None = None,
    ) -> ExecutionResult:
        """
        Execute a complex task with automatic decomposition and orchestration.
        
        Args:
            task: The complex task to execute
            context: Optional additional context
            workspace_name: Optional custom workspace name
            
        Returns:
            ExecutionResult with plan, results, and status
        """
        logger.info(f"Starting orchestrated execution: {task[:100]}...")
        
        try:
            # Step 1: Create execution plan
            plan = await self._create_execution_plan(task, context)
            logger.info(f"Created plan with {len(plan.subtasks)} subtasks")
            
            # Step 2: Create temporary workspace
            workspace = await self._create_workspace(
                plan=plan,
                workspace_name=workspace_name or f"Orchestrated: {task[:50]}",
            )
            logger.info(f"Created workspace: {workspace.workspace_id}")
            
            # Step 3: Execute plan in workspace
            subtask_results = await self._execute_plan(plan, workspace)
            
            # Step 4: Synthesize final result
            final_result = await self._synthesize_results(
                task=task,
                plan=plan,
                subtask_results=subtask_results,
                workspace=workspace,
            )
            
            # Step 5: Complete workspace
            await workspace.complete()
            
            # Capture workspace messages before closing
            workspace_messages = [msg.to_dict() for msg in workspace.get_messages()]
            
            # Export if persistence enabled
            if self.workspace_persistence:
                export_path = await workspace.export_workspace()
                logger.info(f"Workspace exported: {export_path}")
            
            # Close workspace
            await workspace.close()
            
            # Return result
            return ExecutionResult(
                plan=plan,
                workspace_id=workspace.workspace_id,
                final_result=final_result,
                subtask_results=subtask_results,
                success=True,
                workspace_messages=workspace_messages,
                error=None,
                metadata={
                    "num_subtasks": len(plan.subtasks),
                    "num_agents": len(plan.selected_agents),
                },
            )
        
        except Exception as e:
            logger.error(f"Orchestrated execution failed: {e}", exc_info=True)
            
            # Try to capture messages if workspace exists
            workspace_messages = []
            if 'workspace' in locals():
                try:
                    workspace_messages = [msg.to_dict() for msg in workspace.get_messages()]
                except:
                    pass
            
            return ExecutionResult(
                plan=plan if 'plan' in locals() else None,
                workspace_id=workspace.workspace_id if 'workspace' in locals() else None,
                final_result="",
                subtask_results={},
                success=False,
                workspace_messages=workspace_messages,
                error=str(e),
            )
    
    async def _create_execution_plan(
        self,
        task: str,
        context: dict[str, Any] | None,
    ) -> ExecutionPlan:
        """
        Create an execution plan by breaking the task into subtasks.
        
        Args:
            task: The task to decompose
            context: Optional context
            
        Returns:
            ExecutionPlan with subtasks and assignments
        """
        # Build prompt for LLM
        prompt = self._build_planning_prompt(task, context)
        
        # Call LLM
        response = await self.orchestrator._call_llm(prompt)
        
        # Parse response
        plan = self._parse_planning_response(task, response)
        
        return plan
    
    def _build_planning_prompt(
        self,
        task: str,
        context: dict[str, Any] | None,
    ) -> str:
        """Build prompt for task decomposition and planning."""
        # Get agent information
        agents_info = self.orchestrator.list_agents()
        
        prompt = f"""You are an expert task planner for multi-agent systems. Your job is to:
1. Analyze the user's complex task
2. Break it into clear, independent subtasks
3. Assign each subtask to the most suitable agent
4. Define dependencies between subtasks
5. Create an execution order

USER TASK:
{task}

ADDITIONAL CONTEXT:
{json.dumps(context or {}, indent=2)}

AVAILABLE AGENTS:
{json.dumps(agents_info, indent=2)}

INSTRUCTIONS:
1. Break the task into 2-8 concrete subtasks
2. Each subtask should be specific and actionable
3. Assign each subtask to the agent with the best matching skills
4. Identify dependencies (which subtasks must complete before others)
5. Group subtasks into parallel execution stages
6. Provide reasoning for your plan

RESPONSE FORMAT (must be valid JSON):
{{
  "subtasks": [
    {{
      "subtask_id": "subtask_1",
      "description": "Specific description of what needs to be done",
      "assigned_agent_id": "agent_id",
      "assigned_agent_name": "Agent Name",
      "dependencies": [],  // List of subtask_ids this depends on
      "order": 1
    }}
  ],
  "execution_order": [
    ["subtask_1", "subtask_2"],  // Stage 1: These run in parallel
    ["subtask_3"],                // Stage 2: Runs after stage 1
    ["subtask_4", "subtask_5"]   // Stage 3: Runs after stage 2
  ],
  "reasoning": "Explain the overall plan and why subtasks were assigned to specific agents",
  "collaboration_notes": "How agents should collaborate and share information"
}}

IMPORTANT:
- Subtasks should be independent where possible (for parallel execution)
- Only create dependencies when truly necessary
- Assign subtasks to agents whose skills best match the requirements
- Keep subtask descriptions clear and specific

Return ONLY the JSON response, no additional text.
"""
        return prompt
    
    def _parse_planning_response(
        self,
        task: str,
        response: str,
    ) -> ExecutionPlan:
        """Parse LLM response into an ExecutionPlan."""
        try:
            # Clean response
            response = response.strip()
            if response.startswith("```json"):
                response = response[7:]
            if response.startswith("```"):
                response = response[3:]
            if response.endswith("```"):
                response = response[:-3]
            response = response.strip()
            
            data = json.loads(response)
            
            # Parse subtasks
            subtasks = [
                Subtask(
                    subtask_id=st["subtask_id"],
                    description=st["description"],
                    assigned_agent_id=st["assigned_agent_id"],
                    assigned_agent_name=st["assigned_agent_name"],
                    dependencies=st.get("dependencies", []),
                    order=st.get("order", 0),
                )
                for st in data["subtasks"]
            ]
            
            # Get execution order
            execution_order = data.get("execution_order", [])
            
            # Get selected agents (unique)
            selected_agents = list(set(st.assigned_agent_id for st in subtasks))
            
            # Create plan
            plan = ExecutionPlan(
                plan_id=f"plan_{task[:20]}",
                original_task=task,
                subtasks=subtasks,
                execution_order=execution_order,
                selected_agents=selected_agents,
                reasoning=data.get("reasoning", ""),
                metadata={
                    "collaboration_notes": data.get("collaboration_notes", ""),
                },
            )
            
            return plan
        
        except (json.JSONDecodeError, KeyError) as e:
            logger.error(f"Failed to parse planning response: {e}")
            raise ValueError(f"Failed to parse planning response: {e}") from e
    
    async def _create_workspace(
        self,
        plan: ExecutionPlan,
        workspace_name: str,
    ) -> Workspace:
        """
        Create a workspace and add the required agents.
        
        Args:
            plan: Execution plan
            workspace_name: Name for the workspace
            
        Returns:
            Configured Workspace instance
        """
        # Create workspace
        workspace = Workspace(
            name=workspace_name,
            description=f"Orchestrated execution: {plan.original_task[:100]}",
            enable_persistence=self.workspace_persistence,
            auto_cleanup=not self.workspace_persistence,
        )
        
        # Set shared state with plan information
        workspace.set_shared_state("execution_plan", {
            "original_task": plan.original_task,
            "subtasks": [
                {
                    "id": st.subtask_id,
                    "description": st.description,
                    "assigned_to": st.assigned_agent_name,
                }
                for st in plan.subtasks
            ],
            "collaboration_notes": plan.metadata.get("collaboration_notes", ""),
        })
        
        # Add required agents to workspace
        for agent_id in plan.selected_agents:
            if agent_id in self._agents:
                agent = self._agents[agent_id]
                workspace.add_agent(
                    agent=agent,
                    metadata={
                        "assigned_subtasks": [
                            st.subtask_id 
                            for st in plan.subtasks 
                            if st.assigned_agent_id == agent_id
                        ],
                    },
                )
                logger.info(f"Added agent to workspace: {agent_id}")
        
        # Register message callback if provided
        if self.message_callback is not None:
            async def message_handler(msg):
                """Handle workspace messages in real-time."""
                try:
                    self.message_callback(msg.to_dict())
                except Exception as e:
                    logger.error(f"Message callback error: {e}")
            
            workspace.on_message(message_handler)
        
        # Start workspace
        await workspace.start()
        
        return workspace
    
    async def _execute_plan(
        self,
        plan: ExecutionPlan,
        workspace: Workspace,
    ) -> dict[str, str]:
        """
        Execute the plan by running subtasks in order.
        
        Args:
            plan: Execution plan
            workspace: Workspace for execution
            
        Returns:
            Dictionary mapping subtask_id to result
        """
        results: dict[str, str] = {}
        
        # Execute stages in order
        for stage_idx, stage in enumerate(plan.execution_order):
            logger.info(f"Executing stage {stage_idx + 1}/{len(plan.execution_order)}")
            
            # Get subtasks for this stage
            stage_subtasks = [
                st for st in plan.subtasks if st.subtask_id in stage
            ]
            
            # Execute subtasks in parallel (up to max_parallel_subtasks)
            stage_results = await self._execute_stage(
                stage_subtasks,
                workspace,
                results,  # Pass previous results for context
            )
            
            # Update results
            results.update(stage_results)
        
        return results
    
    async def _execute_stage(
        self,
        subtasks: list[Subtask],
        workspace: Workspace,
        previous_results: dict[str, str],
    ) -> dict[str, str]:
        """
        Execute a stage of subtasks with collaboration.
        
        Args:
            subtasks: Subtasks to execute
            workspace: Workspace
            previous_results: Results from previous stages
            
        Returns:
            Dictionary of results for this stage
        """
        results = {}
        
        # Get participants
        participants = {p["name"]: p["participant_id"] for p in workspace.list_participants()}
        
        if self.enable_agent_discussion:
            # Execute with collaboration: agents can discuss and interact
            results = await self._execute_with_collaboration(
                subtasks=subtasks,
                workspace=workspace,
                participants=participants,
                previous_results=previous_results,
            )
        else:
            # Execute without collaboration: parallel independent execution
            results = await self._execute_independently(
                subtasks=subtasks,
                workspace=workspace,
                participants=participants,
                previous_results=previous_results,
            )
        
        return results
    
    async def _execute_with_collaboration(
        self,
        subtasks: list[Subtask],
        workspace: Workspace,
        participants: dict[str, str],
        previous_results: dict[str, str],
    ) -> dict[str, str]:
        """
        Execute subtasks with agent collaboration and discussion.
        
        ADVERSARIAL MODE:
        1. Each agent proposes approach optimized for their specialty (no compromise)
        2. All agents identify flaws, risks, false assumptions in others' work
        3. Each agent defends their approach against critiques
        4. Each synthesizes final result incorporating valid insights
        
        COLLABORATIVE MODE:
        1. See what other agents are working on
        2. Propose their initial approaches
        3. Discuss and provide supportive feedback to each other
        4. Refine their work based on peer input
        5. Produce final results
        
        Args:
            subtasks: Subtasks to execute
            workspace: Workspace
            participants: Name to participant_id mapping
            previous_results: Results from previous stages
            
        Returns:
            Dictionary of results
        """
        mode_name = "adversarial" if self.collaboration_mode == CollaborationMode.ADVERSARIAL else "collaborative"
        logger.info(f"Starting {mode_name} execution for {len(subtasks)} subtasks")
        
        results = {}
        
        # Phase 1: Introduce the collaborative task
        intro_message = self._build_collaboration_intro(subtasks, previous_results, workspace)
        await workspace.broadcast_message(intro_message, sender_id="orchestrator", sender_name="Orchestrator")
        
        # Phase 2: Each agent proposes their initial approach
        if self.collaboration_mode == CollaborationMode.ADVERSARIAL:
            logger.info("Phase 1: Gathering specialty-optimized proposals (adversarial)")
        else:
            logger.info("Phase 1: Gathering initial proposals from agents")
        initial_proposals = await self._gather_initial_proposals(
            subtasks=subtasks,
            workspace=workspace,
            participants=participants,
            previous_results=previous_results,
        )
        
        # Phase 3: Discussion - agents review and comment on each other's proposals
        if len(subtasks) > 1:  # Only if multiple agents
            if self.collaboration_mode == CollaborationMode.ADVERSARIAL:
                logger.info("Phase 2: Critical analysis - identifying flaws and conflicts")
            else:
                logger.info("Phase 2: Collaborative discussion and feedback")
            await self._facilitate_discussion(
                subtasks=subtasks,
                proposals=initial_proposals,
                workspace=workspace,
                participants=participants,
            )
        
        # Phase 4: Agents refine their work based on feedback
        if self.collaboration_mode == CollaborationMode.ADVERSARIAL:
            logger.info("Phase 3: Defense and synthesis - battle-tested results")
        else:
            logger.info("Phase 3: Refining work based on collaboration")
        refined_results = await self._refine_with_feedback(
            subtasks=subtasks,
            proposals=initial_proposals,
            workspace=workspace,
            participants=participants,
        )
        
        # Phase 5: Finalize results
        for subtask_id, result in refined_results.items():
            results[subtask_id] = result
            
            # Store as artifact
            workspace.add_artifact(
                name=f"result_{subtask_id}.txt",
                artifact_type="result",
                content=result,
                created_by=subtask_id,
                metadata={
                    "subtask_id": subtask_id,
                    "collaboration_mode": self.collaboration_mode.value,
                },
            )
        
        logger.info("Collaborative execution completed")
        return results
    
    async def _execute_independently(
        self,
        subtasks: list[Subtask],
        workspace: Workspace,
        participants: dict[str, str],
        previous_results: dict[str, str],
    ) -> dict[str, str]:
        """
        Execute subtasks independently without collaboration.
        
        Args:
            subtasks: Subtasks to execute
            workspace: Workspace
            participants: Name to participant_id mapping
            previous_results: Results from previous stages
            
        Returns:
            Dictionary of results
        """
        results = {}
        
        # Create tasks for parallel execution
        tasks = []
        for subtask in subtasks:
            # Find participant ID for assigned agent
            participant_id = participants.get(subtask.assigned_agent_name)
            
            if participant_id:
                # Build context-aware prompt
                prompt = self._build_subtask_prompt(subtask, previous_results, workspace)
                
                # Create execution task
                task = self._execute_subtask(
                    subtask=subtask,
                    participant_id=participant_id,
                    prompt=prompt,
                    workspace=workspace,
                )
                tasks.append((subtask.subtask_id, task))
            else:
                logger.warning(f"Agent not found for subtask: {subtask.subtask_id}")
        
        # Execute in parallel
        for subtask_id, task in tasks:
            try:
                result = await task
                results[subtask_id] = result
                
                # Store as artifact
                workspace.add_artifact(
                    name=f"result_{subtask_id}.txt",
                    artifact_type="result",
                    content=result,
                    created_by=subtask_id,
                    metadata={"subtask_id": subtask_id},
                )
            except Exception as e:
                logger.error(f"Subtask {subtask_id} failed: {e}")
                results[subtask_id] = f"Error: {str(e)}"
        
        return results
    
    def _build_collaboration_intro(
        self,
        subtasks: list[Subtask],
        previous_results: dict[str, str],
        workspace: Workspace,
    ) -> str:
        """Build introduction message for session."""
        plan_info = workspace.get_shared_state("execution_plan", {})
        
        if self.collaboration_mode == CollaborationMode.ADVERSARIAL:
            intro = [
                "⚔️ ADVERSARIAL COLLABORATION SESSION",
                "",
                f"Complex task requiring diverse expertise: {plan_info.get('original_task', '')}",
                "",
                "SPECIALIST ASSIGNMENTS:",
            ]
            
            for subtask in subtasks:
                intro.append(f"  • {subtask.assigned_agent_name}: {subtask.description}")
            
            intro.extend([
                "",
                "ADVERSARIAL PROCESS:",
                "1. Each specialist proposes their optimal approach (NO compromise for consensus)",
                "2. All specialists identify flaws, risks, and false assumptions in others' proposals",
                "3. Each specialist defends their approach against critiques",
                "4. Synthesis: Each produces final optimized result incorporating valid insights",
                "",
                "Goal: Force conflicting perspectives to collide → recombine → produce superior solutions.",
                "You must OPTIMIZE FOR YOUR SPECIALTY, regardless of what others propose.",
            ])
        else:
            intro = [
                "🤝 COLLABORATIVE WORKSPACE SESSION",
                "",
                f"We're working together on: {plan_info.get('original_task', '')}",
                "",
                "TEAM ASSIGNMENTS:",
            ]
            
            for subtask in subtasks:
                intro.append(f"  • {subtask.assigned_agent_name}: {subtask.description}")
            
            intro.extend([
                "",
                "HOW WE'LL COLLABORATE:",
                "1. Each of you will propose your initial approach",
                "2. You'll review and provide feedback on each other's proposals",
                "3. You'll refine your work based on the team's insights",
                "4. Together, we'll create a cohesive solution",
                "",
                "Let's begin! Share your thoughts, build on each other's ideas, and create something great together.",
            ])
        
        return "\n".join(intro)
    
    async def _gather_initial_proposals(
        self,
        subtasks: list[Subtask],
        workspace: Workspace,
        participants: dict[str, str],
        previous_results: dict[str, str],
    ) -> dict[str, str]:
        """Gather initial proposals from all agents."""
        proposals = {}
        
        # Send initial task to each agent
        tasks = []
        for subtask in subtasks:
            participant_id = participants.get(subtask.assigned_agent_name)
            
            if participant_id:
                prompt = self._build_proposal_prompt(subtask, previous_results, workspace)
                task = workspace.send_message_to_agent(participant_id, prompt)
                tasks.append((subtask.subtask_id, subtask.assigned_agent_name, task))
        
        # Gather proposals
        for subtask_id, agent_name, task in tasks:
            try:
                proposal = await task
                proposals[subtask_id] = proposal
                logger.info(f"Received proposal from {agent_name} for {subtask_id}")
            except Exception as e:
                logger.error(f"Failed to get proposal from {agent_name}: {e}")
                proposals[subtask_id] = f"Error: {str(e)}"
        
        return proposals
    
    async def _facilitate_discussion(
        self,
        subtasks: list[Subtask],
        proposals: dict[str, str],
        workspace: Workspace,
        participants: dict[str, str],
    ) -> None:
        """Facilitate discussion where agents provide feedback to each other."""
        # Create a summary of all proposals for context
        summary = self._build_proposals_summary(subtasks, proposals)
        
        # Each agent reviews other agents' proposals and provides feedback
        feedback_tasks = []
        for subtask in subtasks:
            participant_id = participants.get(subtask.assigned_agent_name)
            
            if participant_id:
                # Build feedback request for this agent
                feedback_prompt = self._build_feedback_prompt(
                    subtask=subtask,
                    all_subtasks=subtasks,
                    proposals=proposals,
                    summary=summary,
                )
                
                task = workspace.send_message_to_agent(participant_id, feedback_prompt)
                feedback_tasks.append((subtask.assigned_agent_name, task))
        
        # Gather feedback from all agents
        for agent_name, task in feedback_tasks:
            try:
                feedback = await task
                logger.info(f"Received feedback from {agent_name}")
                
                # Store feedback as artifact
                workspace.add_artifact(
                    name=f"feedback_{agent_name}.txt",
                    artifact_type="feedback",
                    content=feedback,
                    created_by=agent_name,
                    metadata={"phase": "discussion"},
                )
            except Exception as e:
                logger.error(f"Failed to get feedback from {agent_name}: {e}")
    
    async def _refine_with_feedback(
        self,
        subtasks: list[Subtask],
        proposals: dict[str, str],
        workspace: Workspace,
        participants: dict[str, str],
    ) -> dict[str, str]:
        """Have agents refine their work based on peer feedback."""
        refined_results = {}
        
        # Get all feedback artifacts
        feedback_artifacts = workspace.get_artifacts(artifact_type="feedback")
        all_feedback = "\n\n".join([
            f"Feedback from {a.created_by}:\n{a.content}"
            for a in feedback_artifacts
        ])
        
        # Each agent refines their work
        refine_tasks = []
        for subtask in subtasks:
            participant_id = participants.get(subtask.assigned_agent_name)
            
            if participant_id:
                original_proposal = proposals.get(subtask.subtask_id, "")
                
                refine_prompt = self._build_refinement_prompt(
                    subtask=subtask,
                    original_proposal=original_proposal,
                    all_feedback=all_feedback,
                )
                
                task = workspace.send_message_to_agent(participant_id, refine_prompt)
                refine_tasks.append((subtask.subtask_id, subtask.assigned_agent_name, task))
        
        # Gather refined results
        for subtask_id, agent_name, task in refine_tasks:
            try:
                refined = await task
                refined_results[subtask_id] = refined
                logger.info(f"Received refined result from {agent_name}")
            except Exception as e:
                logger.error(f"Failed to get refined result from {agent_name}: {e}")
                # Fallback to original proposal
                refined_results[subtask_id] = proposals.get(subtask_id, f"Error: {str(e)}")
        
        return refined_results
    
    def _build_proposal_prompt(
        self,
        subtask: Subtask,
        previous_results: dict[str, str],
        workspace: Workspace,
    ) -> str:
        """Build prompt for initial proposal."""
        plan_info = workspace.get_shared_state("execution_plan", {})
        
        if self.collaboration_mode == CollaborationMode.ADVERSARIAL:
            parts = [
                "🎯 SPECIALTY PROPOSAL PHASE",
                "",
                f"Complex task requiring your expertise: {plan_info.get('original_task', '')}",
                "",
                f"YOUR SPECIALIZED TASK: {subtask.description}",
                "",
            ]
            
            # Add context from previous stages if available
            if subtask.dependencies and previous_results:
                parts.append("CONTEXT FROM PREVIOUS WORK:")
                for dep_id in subtask.dependencies:
                    if dep_id in previous_results:
                        parts.append(f"\n{dep_id}:")
                        parts.append(previous_results[dep_id][:300] + "...")
                parts.append("")
            
            parts.extend([
                "⚠️ CRITICAL INSTRUCTIONS:",
                "• You must optimize for YOUR specialty, regardless of what others propose",
                "• Take STRONG positions based on your domain expertise",
                "• Do NOT soften your approach for consensus",
                "• Do NOT blend with others - advocate for your specialty",
                "• Challenge assumptions that conflict with your expertise",
                "",
                "Provide your EXPERT PROPOSAL:",
                "1. Your recommended approach optimized for your specialty",
                "2. Key principles from your domain that MUST be followed",
                "3. Risks you foresee if your expertise is ignored",
                "4. Non-negotiable requirements from your perspective",
                "",
                "Be direct, uncompromising, and advocate strongly for your specialty.",
                "You'll see others' proposals later - they may conflict with yours (that's the goal).",
            ])
        else:
            parts = [
                "📝 INITIAL PROPOSAL PHASE",
                "",
                f"You're part of a collaborative team working on: {plan_info.get('original_task', '')}",
                "",
                f"YOUR TASK: {subtask.description}",
                "",
            ]
            
            # Add context from previous stages if available
            if subtask.dependencies and previous_results:
                parts.append("CONTEXT FROM PREVIOUS WORK:")
                for dep_id in subtask.dependencies:
                    if dep_id in previous_results:
                        parts.append(f"\n{dep_id}:")
                        parts.append(previous_results[dep_id][:300] + "...")
                parts.append("")
            
            parts.extend([
                "Please share your INITIAL APPROACH:",
                "1. What's your plan for completing this task?",
                "2. What key ideas or methods will you use?",
                "3. How will your work connect with the team's overall goal?",
                "",
                "Be clear and specific, but don't finalize yet - you'll get feedback from teammates!",
            ])
        
        return "\n".join(parts)
    
    def _build_proposals_summary(
        self,
        subtasks: list[Subtask],
        proposals: dict[str, str],
    ) -> str:
        """Build summary of all proposals."""
        summary_parts = ["TEAM PROPOSALS SUMMARY:", ""]
        
        for subtask in subtasks:
            proposal = proposals.get(subtask.subtask_id, "No proposal")
            summary_parts.append(f"{subtask.assigned_agent_name} ({subtask.description}):")
            summary_parts.append(proposal[:400] + ("..." if len(proposal) > 400 else ""))
            summary_parts.append("")
        
        return "\n".join(summary_parts)
    
    def _build_feedback_prompt(
        self,
        subtask: Subtask,
        all_subtasks: list[Subtask],
        proposals: dict[str, str],
        summary: str,
    ) -> str:
        """Build prompt for providing feedback."""
        if self.collaboration_mode == CollaborationMode.ADVERSARIAL:
            parts = [
                "🔍 CRITICAL ANALYSIS PHASE",
                "",
                "You've seen other specialists' proposals. Now identify problems from your expertise.",
                "",
                summary,
                "",
                "Your task: IDENTIFY FLAWS, RISKS, and FALSE ASSUMPTIONS",
                "",
                "For EACH other specialist's proposal, analyze:",
                "1. What flaws or blind spots do you see from your domain expertise?",
                "2. What risks are they missing or underestimating?",
                "3. Where do their recommendations conflict with your specialty?",
                "4. What false assumptions are they making?",
                "5. What will break if we follow their approach uncritically?",
                "",
                "NOT synergy. NOT compliments. NOT 'how can we work together?'",
                "FORCE CONFLICT. Surface problems NOW, not after implementation.",
                "",
                "Be specific, direct, and uncompromising. This is about finding what's wrong,",
                "not about being nice. Real issues need to surface before they become failures.",
            ]
        else:
            parts = [
                "💬 COLLABORATIVE FEEDBACK PHASE",
                "",
                "Your teammates have shared their initial approaches. Let's help each other!",
                "",
                summary,
                "",
                "Please provide CONSTRUCTIVE FEEDBACK:",
                "1. What ideas from other teammates could enhance your approach?",
                "2. What insights can you share that might help others?",
                "3. Do you see any opportunities for synergy or better integration?",
                "4. Any concerns or suggestions for the overall approach?",
                "",
                "Be supportive and specific! We're building something together.",
            ]
        
        return "\n".join(parts)
    
    def _build_refinement_prompt(
        self,
        subtask: Subtask,
        original_proposal: str,
        all_feedback: str,
    ) -> str:
        """Build prompt for refining work based on feedback."""
        if self.collaboration_mode == CollaborationMode.ADVERSARIAL:
            parts = [
                "🛡️ DEFENSE & SYNTHESIS PHASE",
                "",
                "You've received critiques. Now defend your approach and synthesize the final result.",
                "",
                "YOUR ORIGINAL PROPOSAL:",
                original_proposal,
                "",
                "CRITIQUES FROM OTHER SPECIALISTS:",
                all_feedback,
                "",
                f"YOUR TASK (to complete): {subtask.description}",
                "",
                "Step 1: DEFEND YOUR APPROACH",
                "• Address each valid critique - explain how you'll adapt",
                "• Push back where critiques miss important context from your specialty",
                "• Explain trade-offs others don't see from their limited perspective",
                "",
                "Step 2: SYNTHESIZE FINAL RESULT",
                "• Incorporate insights that genuinely strengthen your approach",
                "• Maintain your core expertise and non-negotiables",
                "• Acknowledge interdependencies discovered through conflict",
                "• Produce your COMPLETE, FINAL, OPTIMIZED deliverable",
                "",
                "This is where emergence happens: conflicting perspectives collide,",
                "then recombine into something better than any single viewpoint.",
                "",
                "Provide your FINAL result - battle-tested through adversarial pressure.",
            ]
        else:
            parts = [
                "✨ REFINEMENT PHASE",
                "",
                "Great collaboration! Now let's refine your work based on the team's insights.",
                "",
                "YOUR ORIGINAL PROPOSAL:",
                original_proposal,
                "",
                "TEAM FEEDBACK:",
                all_feedback,
                "",
                f"YOUR TASK (to complete): {subtask.description}",
                "",
                "Please provide your FINAL, REFINED RESULT:",
                "1. Incorporate valuable insights from the feedback",
                "2. Ensure your work integrates well with the team's approach",
                "3. Complete your task fully and thoughtfully",
                "",
                "This is your final deliverable - make it great!",
            ]
        
        return "\n".join(parts)
    
    def _build_subtask_prompt(
        self,
        subtask: Subtask,
        previous_results: dict[str, str],
        workspace: Workspace,
    ) -> str:
        """Build a context-aware prompt for a subtask."""
        # Get plan info from shared state
        plan_info = workspace.get_shared_state("execution_plan", {})
        
        prompt_parts = [
            f"You are working on a collaborative project: {plan_info.get('original_task', '')}",
            "",
            f"YOUR SUBTASK: {subtask.description}",
            "",
        ]
        
        # Add previous results if there are dependencies
        if subtask.dependencies and previous_results:
            prompt_parts.append("PREVIOUS RESULTS (from dependent subtasks):")
            for dep_id in subtask.dependencies:
                if dep_id in previous_results:
                    prompt_parts.append(f"\n{dep_id}:")
                    prompt_parts.append(previous_results[dep_id][:500] + "...")  # Truncate
            prompt_parts.append("")
        
        # Add collaboration notes
        if plan_info.get("collaboration_notes"):
            prompt_parts.append("COLLABORATION NOTES:")
            prompt_parts.append(plan_info["collaboration_notes"])
            prompt_parts.append("")
        
        # Add artifacts if available
        artifacts = workspace.get_artifacts()
        if artifacts:
            prompt_parts.append(f"AVAILABLE ARTIFACTS: {len(artifacts)} artifacts in workspace")
            prompt_parts.append("")
        
        prompt_parts.append("Please complete your subtask. You can discuss with other agents if needed.")
        
        return "\n".join(prompt_parts)
    
    async def _execute_subtask(
        self,
        subtask: Subtask,
        participant_id: str,
        prompt: str,
        workspace: Workspace,
    ) -> str:
        """Execute a single subtask."""
        logger.info(f"Executing subtask: {subtask.subtask_id}")
        
        # Mark as in progress
        subtask.status = "in_progress"
        
        # Send message to agent
        try:
            result = await workspace.send_message_to_agent(
                participant_id=participant_id,
                message=prompt,
            )
            
            # Mark as completed
            subtask.status = "completed"
            subtask.result = result
            
            logger.info(f"Subtask completed: {subtask.subtask_id}")
            return result
        
        except Exception as e:
            # Mark as failed
            subtask.status = "failed"
            logger.error(f"Subtask failed: {subtask.subtask_id} - {e}")
            raise
    
    async def _synthesize_results(
        self,
        task: str,
        plan: ExecutionPlan,
        subtask_results: dict[str, str],
        workspace: Workspace,
    ) -> str:
        """
        Synthesize final result from subtask results.
        
        Args:
            task: Original task
            plan: Execution plan
            subtask_results: Results from all subtasks
            workspace: Workspace
            
        Returns:
            Synthesized final result
        """
        # Build synthesis prompt
        prompt = f"""You are synthesizing the final result for a complex task that was broken into subtasks.

ORIGINAL TASK:
{task}

EXECUTION PLAN:
{plan.reasoning}

SUBTASK RESULTS:
"""
        
        for subtask in plan.subtasks:
            result = subtask_results.get(subtask.subtask_id, "No result")
            prompt += f"\n{subtask.subtask_id} ({subtask.assigned_agent_name}): {subtask.description}\n"
            prompt += f"Result: {result}\n"
        
        prompt += """
Please synthesize these subtask results into a comprehensive final answer to the original task.
Your synthesis should:
1. Integrate all relevant information from the subtasks
2. Provide a coherent, complete response
3. Address the original task fully
4. Be well-structured and clear
"""
        
        # Call LLM for synthesis
        try:
            final_result = await self.orchestrator._call_llm(prompt)
            
            # Store final result as artifact
            workspace.add_artifact(
                name="final_result.txt",
                artifact_type="result",
                content=final_result,
                created_by="orchestrator",
                metadata={"is_final": True},
            )
            
            return final_result
        
        except Exception as e:
            logger.error(f"Synthesis failed: {e}")
            # Fallback: concatenate results
            return "\n\n".join(
                f"{st.description}:\n{subtask_results.get(st.subtask_id, 'No result')}"
                for st in plan.subtasks
            )
    
    def __repr__(self) -> str:
        """String representation."""
        return (
            f"OrchestratedWorkspace(agents={len(self._agents)}, "
            f"mode={self.collaboration_mode.value}, "
            f"discussion_enabled={self.enable_agent_discussion})"
        )

