"""Workflow state definitions for LangGraph trading workflow.

This module defines the TypedDict state classes used by the LangGraph
state graph to track workflow progress and agent outputs.
"""

import operator
from typing import Annotated, Any, Dict, List, Optional, TypedDict

from openclaw.agents.bear_researcher import BearReport
from openclaw.agents.bull_researcher import BullReport
from openclaw.agents.fundamental_analyst import FundamentalReport
from openclaw.agents.market_analyst import TechnicalReport
from openclaw.agents.risk_manager import RiskReport
from openclaw.agents.sentiment_analyst import SentimentReport


class AgentConfig(TypedDict):
    """Configuration for an agent in the workflow."""

    agent_id: str
    initial_capital: float
    skill_level: float


class WorkflowConfig(TypedDict):
    """Configuration for the trading workflow."""

    symbol: str
    market_analyst: AgentConfig
    sentiment_analyst: AgentConfig
    fundamental_analyst: AgentConfig
    bull_researcher: AgentConfig
    bear_researcher: AgentConfig
    risk_manager: AgentConfig
    trader: AgentConfig


class AnalysisState(TypedDict):
    """State for parallel analysis phase.

    This state is populated by the three parallel analysis nodes:
    - MarketAnalysis (technical)
    - SentimentAnalysis (sentiment)
    - FundamentalAnalysis (fundamental)
    """

    technical_report: Optional[TechnicalReport]
    sentiment_report: Optional[SentimentReport]
    fundamental_report: Optional[FundamentalReport]
    analysis_errors: List[str]


class DebateState(TypedDict):
    """State for bull-bear debate phase.

    This state is populated by the BullBearDebate node.
    """

    bull_report: Optional[BullReport]
    bear_report: Optional[BearReport]
    debate_errors: List[str]


class FusionState(TypedDict):
    """State for decision fusion phase.

    This state is populated by the DecisionFusion node.
    """

    fused_decision: Optional[Dict[str, Any]]
    confidence_score: float
    recommendation: str
    fusion_errors: List[str]


class RiskState(TypedDict):
    """State for risk assessment phase.

    This state is populated by the RiskAssessment node.
    """

    risk_report: Optional[RiskReport]
    position_size: float
    approved: bool
    risk_errors: List[str]


def _replace(existing: Any, new: Any) -> Any:
    """Reducer that replaces the existing value with the new value."""
    return new


class TradingWorkflowState(TypedDict):
    """Complete state for the trading workflow.

    This TypedDict is passed between all nodes in the LangGraph
    state graph. Each node reads from and writes to specific fields.

    Note: Annotated fields with reducers allow concurrent updates from
    parallel nodes. The reducers specify how to combine multiple values.
    """

    # Configuration
    config: WorkflowConfig

    # Execution tracking
    # current_step uses 'replace' reducer - last write wins
    current_step: Annotated[str, _replace]
    # completed_steps uses 'add' reducer - combines lists from parallel nodes
    completed_steps: Annotated[List[str], operator.add]
    # errors uses 'add' reducer - combines error lists
    errors: Annotated[List[str], operator.add]

    # Analysis phase outputs (each set by one specific node)
    technical_report: Annotated[Optional[TechnicalReport], _replace]
    sentiment_report: Annotated[Optional[SentimentReport], _replace]
    fundamental_report: Annotated[Optional[FundamentalReport], _replace]

    # Debate phase outputs
    bull_report: Annotated[Optional[BullReport], _replace]
    bear_report: Annotated[Optional[BearReport], _replace]

    # Fusion phase outputs
    fused_decision: Annotated[Optional[Dict[str, Any]], _replace]

    # Risk phase outputs
    risk_report: Annotated[Optional[RiskReport], _replace]

    # Final decision (from risk assessment)
    final_decision: Annotated[Optional[Dict[str, Any]], _replace]

    # Order execution result (from TraderAgent after risk_assessment)
    execution_result: Annotated[Optional[Dict[str, Any]], _replace]

    # Optional market data
    market_data: Annotated[Optional[Dict[str, Any]], _replace]


def create_initial_state(symbol: str, initial_capital: float = 1000.0) -> TradingWorkflowState:
    """Create the initial state for a trading workflow.

    Args:
        symbol: The trading symbol to analyze
        initial_capital: Initial capital for each agent

    Returns:
        Initialized TradingWorkflowState
    """
    return {
        "config": {
            "symbol": symbol,
            "market_analyst": {
                "agent_id": f"market_analyst_{symbol}",
                "initial_capital": initial_capital,
                "skill_level": 0.7,
            },
            "sentiment_analyst": {
                "agent_id": f"sentiment_analyst_{symbol}",
                "initial_capital": initial_capital,
                "skill_level": 0.6,
            },
            "fundamental_analyst": {
                "agent_id": f"fundamental_analyst_{symbol}",
                "initial_capital": initial_capital,
                "skill_level": 0.65,
            },
            "bull_researcher": {
                "agent_id": f"bull_researcher_{symbol}",
                "initial_capital": initial_capital,
                "skill_level": 0.7,
            },
            "bear_researcher": {
                "agent_id": f"bear_researcher_{symbol}",
                "initial_capital": initial_capital,
                "skill_level": 0.7,
            },
            "risk_manager": {
                "agent_id": f"risk_manager_{symbol}",
                "initial_capital": initial_capital,
                "skill_level": 0.8,
            },
            "trader": {
                "agent_id": f"trader_{symbol}",
                "initial_capital": initial_capital,
                "skill_level": 0.7,
            },
        },
        "current_step": "START",
        "completed_steps": [],
        "errors": [],
        "technical_report": None,
        "sentiment_report": None,
        "fundamental_report": None,
        "bull_report": None,
        "bear_report": None,
        "fused_decision": None,
        "risk_report": None,
        "final_decision": None,
        "execution_result": None,
        "market_data": None,
    }


def get_state_summary(state: TradingWorkflowState) -> Dict[str, Any]:
    """Get a summary of the current workflow state.

    Args:
        state: Current workflow state

    Returns:
        Dictionary with state summary
    """
    return {
        "symbol": state["config"]["symbol"],
        "current_step": state["current_step"],
        "completed_steps": state["completed_steps"],
        "has_technical": state["technical_report"] is not None,
        "has_sentiment": state["sentiment_report"] is not None,
        "has_fundamental": state["fundamental_report"] is not None,
        "has_bull": state["bull_report"] is not None,
        "has_bear": state["bear_report"] is not None,
        "has_fusion": state["fused_decision"] is not None,
        "has_risk": state["risk_report"] is not None,
        "has_final": state["final_decision"] is not None,
        "error_count": len(state["errors"]),
    }
