"""
Decision Engine for analyzing performance and generating improvement plans
"""

import json
import time
import uuid
from typing import Any, Dict, List, Optional

from openfund_agent.models.decision import (
    CodeModification,
    ImprovementPlan,
    Issue,
    PerformanceAnalysis,
    ReviewRequest,
)
from openfund_agent.models.performance import PerformanceReport


class DecisionEngine:
    """
    Agent decision engine using Claude model for analysis and decision-making

    This engine analyzes strategy performance, identifies issues, and generates
    improvement plans using Claude AI.
    """

    def __init__(self, claude_client: Any, model_version: str = "claude-3-5-sonnet-20241022"):
        """
        Initialize the decision engine

        Args:
            claude_client: Claude API client instance
            model_version: Claude model version to use
        """
        self.client = claude_client
        self.model = model_version
        self.decision_history: List[Dict[str, Any]] = []

    def analyze_performance(
        self,
        performance_report: PerformanceReport,
        strategy_config: Dict[str, Any],
    ) -> PerformanceAnalysis:
        """
        Analyze strategy performance using Claude

        Args:
            performance_report: Performance report to analyze
            strategy_config: Current strategy configuration

        Returns:
            PerformanceAnalysis with insights and ratings

        Raises:
            Exception: If Claude API call fails
        """
        from openfund_agent.decision.prompts import PromptTemplates

        # Prepare prompt with performance data
        prompt = PromptTemplates.PERFORMANCE_ANALYSIS.format(
            strategy_config=json.dumps(strategy_config, indent=2),
            total_trades=performance_report.metrics.total_trades,
            win_rate=performance_report.metrics.win_rate * 100,
            profit_factor=performance_report.metrics.profit_factor,
            max_drawdown=performance_report.metrics.max_drawdown * 100,
            sharpe_ratio=performance_report.metrics.sharpe_ratio,
            trade_history=self._format_trade_history(performance_report.trade_list[:10]),
        )

        # Call Claude API
        response = self.client.messages.create(
            model=self.model,
            max_tokens=2000,
            messages=[{"role": "user", "content": prompt}],
        )

        # Parse response
        analysis_data = json.loads(response.content[0].text)

        # Create PerformanceAnalysis object
        analysis = PerformanceAnalysis(
            overall_rating=analysis_data.get("overall_rating", "good"),
            strengths=analysis_data.get("strengths", []),
            weaknesses=analysis_data.get("weaknesses", []),
            key_metrics=analysis_data.get("key_metrics", {}),
            trend_analysis=analysis_data.get("trend_analysis", ""),
            confidence=analysis_data.get("confidence", 0.8),
            timestamp=int(time.time()),
        )

        # Record decision
        self.decision_history.append(
            {
                "type": "performance_analysis",
                "timestamp": analysis.timestamp,
                "input": {
                    "metrics": performance_report.metrics.__dict__,
                    "strategy": strategy_config,
                },
                "output": analysis.__dict__,
            }
        )

        return analysis

    def identify_issues(self, analysis: PerformanceAnalysis) -> List[Issue]:
        """
        Identify strategy issues based on performance analysis

        Args:
            analysis: Performance analysis result

        Returns:
            List of identified issues

        Raises:
            Exception: If Claude API call fails
        """
        from openfund_agent.decision.prompts import PromptTemplates

        # Prepare prompt
        prompt = PromptTemplates.ISSUE_IDENTIFICATION.format(
            performance_analysis=json.dumps(
                {
                    "overall_rating": analysis.overall_rating,
                    "strengths": analysis.strengths,
                    "weaknesses": analysis.weaknesses,
                    "key_metrics": analysis.key_metrics,
                    "trend_analysis": analysis.trend_analysis,
                },
                indent=2,
            )
        )

        # Call Claude API
        response = self.client.messages.create(
            model=self.model,
            max_tokens=2000,
            messages=[{"role": "user", "content": prompt}],
        )

        # Parse response
        issues_data = json.loads(response.content[0].text)

        # Create Issue objects
        issues = []
        for issue_dict in issues_data:
            issue = Issue(
                issue_id=str(uuid.uuid4()),
                severity=issue_dict.get("severity", "medium"),
                category=issue_dict.get("category", "performance"),
                description=issue_dict.get("description", ""),
                affected_components=issue_dict.get("affected_components", []),
                suggested_fix=issue_dict.get("suggested_fix", ""),
                priority=issue_dict.get("priority", 5),
            )
            issues.append(issue)

        # Record decision
        self.decision_history.append(
            {
                "type": "issue_identification",
                "timestamp": int(time.time()),
                "input": {"analysis": analysis.__dict__},
                "output": [issue.__dict__ for issue in issues],
            }
        )

        return issues

    def generate_improvement_plan(
        self, issues: List[Issue], current_strategy: Dict[str, Any]
    ) -> ImprovementPlan:
        """
        Generate improvement plan based on identified issues

        Args:
            issues: List of identified issues
            current_strategy: Current strategy configuration

        Returns:
            ImprovementPlan with proposed modifications

        Raises:
            Exception: If Claude API call fails
        """
        from openfund_agent.decision.prompts import PromptTemplates

        # Prepare prompt
        prompt = PromptTemplates.IMPROVEMENT_PLAN.format(
            issues=json.dumps([issue.__dict__ for issue in issues], indent=2),
            current_strategy=json.dumps(current_strategy, indent=2),
        )

        # Call Claude API
        response = self.client.messages.create(
            model=self.model,
            max_tokens=3000,
            messages=[{"role": "user", "content": prompt}],
        )

        # Parse response
        plan_data = json.loads(response.content[0].text)

        # Create CodeModification objects
        modifications = []
        for mod_dict in plan_data.get("modifications", []):
            modification = CodeModification(
                file_path=mod_dict.get("file_path", ""),
                modification_type=mod_dict.get("modification_type", "parameter"),
                target_component=mod_dict.get("target_component", ""),
                current_value=mod_dict.get("current_value"),
                new_value=mod_dict.get("new_value"),
                description=mod_dict.get("description", ""),
            )
            modifications.append(modification)

        # Create ImprovementPlan
        plan = ImprovementPlan(
            plan_id=str(uuid.uuid4()),
            issues_addressed=[issue.issue_id for issue in issues],
            modifications=modifications,
            expected_impact=plan_data.get("expected_impact", {}),
            risk_level=plan_data.get("risk_level", "medium"),
            requires_review=plan_data.get("requires_review", False),
            rationale=plan_data.get("rationale", ""),
            timestamp=int(time.time()),
        )

        # Record decision
        self.decision_history.append(
            {
                "type": "improvement_plan",
                "timestamp": plan.timestamp,
                "input": {
                    "issues": [issue.__dict__ for issue in issues],
                    "strategy": current_strategy,
                },
                "output": plan.__dict__,
            }
        )

        return plan

    def request_human_review(self, plan: ImprovementPlan, reason: str) -> ReviewRequest:
        """
        Create a human review request for high-risk modifications

        Args:
            plan: Improvement plan requiring review
            reason: Reason for review request

        Returns:
            ReviewRequest object
        """
        # Determine urgency based on risk level
        urgency_map = {"low": "low", "medium": "medium", "high": "high"}
        urgency = urgency_map.get(plan.risk_level, "medium")

        request = ReviewRequest(
            request_id=str(uuid.uuid4()),
            plan=plan,
            reason=reason,
            urgency=urgency,
            status="pending",
            reviewer_notes=None,
            timestamp=int(time.time()),
        )

        # Record decision
        self.decision_history.append(
            {
                "type": "review_request",
                "timestamp": request.timestamp,
                "input": {"plan": plan.__dict__, "reason": reason},
                "output": request.__dict__,
            }
        )

        return request

    def _format_trade_history(self, trades: List[Any]) -> str:
        """
        Format trade history for prompt

        Args:
            trades: List of TradeMetrics objects

        Returns:
            Formatted string representation
        """
        if not trades:
            return "No trades available"

        lines = []
        for trade in trades:
            lines.append(
                f"- {trade.symbol} {trade.side}: "
                f"Entry={trade.entry_price:.2f}, Exit={trade.exit_price:.2f}, "
                f"PnL={trade.pnl_percent:.2%}, Time={trade.holding_time}s"
            )

        return "\n".join(lines)
