"""
Serialization utilities for performance data

This module provides functions to serialize performance data into formats
suitable for transmission to the Agent decision center (Claude model).
"""

import json
from typing import Dict, Any, List
from dataclasses import asdict
from openfund_agent.models.performance import (
    TradeMetrics,
    PeriodMetrics,
    PerformanceReport,
)


def serialize_trade_metrics(trade_metrics: TradeMetrics) -> Dict[str, Any]:
    """
    Serialize TradeMetrics to dictionary

    Args:
        trade_metrics: TradeMetrics object to serialize

    Returns:
        Dictionary representation of trade metrics
    """
    return asdict(trade_metrics)


def serialize_period_metrics(period_metrics: PeriodMetrics) -> Dict[str, Any]:
    """
    Serialize PeriodMetrics to dictionary

    Args:
        period_metrics: PeriodMetrics object to serialize

    Returns:
        Dictionary representation of period metrics
    """
    data = asdict(period_metrics)

    # Convert infinity to string for JSON compatibility
    if data["profit_factor"] == float("inf"):
        data["profit_factor"] = "infinity"

    return data


def serialize_performance_report(report: PerformanceReport) -> Dict[str, Any]:
    """
    Serialize PerformanceReport to dictionary

    Args:
        report: PerformanceReport object to serialize

    Returns:
        Dictionary representation of performance report
    """
    return {
        "period": report.period,
        "start_time": report.start_time,
        "end_time": report.end_time,
        "metrics": serialize_period_metrics(report.metrics),
        "trade_list": [serialize_trade_metrics(tm) for tm in report.trade_list],
        "equity_curve": report.equity_curve,
        "anomalies": report.anomalies,
    }


def serialize_to_json(report: PerformanceReport) -> str:
    """
    Serialize PerformanceReport to JSON string

    Args:
        report: PerformanceReport object to serialize

    Returns:
        JSON string representation
    """
    data = serialize_performance_report(report)
    return json.dumps(data, indent=2)


def format_for_claude(report: PerformanceReport) -> str:
    """
    Format PerformanceReport for Claude model consumption

    This creates a human-readable text format optimized for LLM understanding.

    Args:
        report: PerformanceReport object to format

    Returns:
        Formatted string suitable for Claude model
    """
    metrics = report.metrics

    lines = [
        "=== Trading Performance Report ===",
        f"\nPeriod: {report.period}",
        f"Time Range: {report.start_time} to {report.end_time}",
        f"\n--- Summary Metrics ---",
        f"Total Trades: {metrics.total_trades}",
        f"Winning Trades: {metrics.winning_trades}",
        f"Losing Trades: {metrics.losing_trades}",
        f"Win Rate: {metrics.win_rate*100:.2f}%",
        f"\n--- Profitability ---",
        f"Total P&L: ${metrics.total_pnl:.2f}",
        f"Average Win: ${metrics.avg_win:.2f}",
        f"Average Loss: ${metrics.avg_loss:.2f}",
    ]

    # Handle infinity profit factor
    if metrics.profit_factor == float("inf"):
        lines.append("Profit Factor: ∞ (no losses)")
    else:
        lines.append(f"Profit Factor: {metrics.profit_factor:.2f}")

    lines.extend(
        [
            f"\n--- Risk Metrics ---",
            f"Maximum Drawdown: {metrics.max_drawdown*100:.2f}%",
            f"Sharpe Ratio: {metrics.sharpe_ratio:.2f}",
            f"Sortino Ratio: {metrics.sortino_ratio:.2f}",
        ]
    )

    # Add trade details
    if report.trade_list:
        lines.append(f"\n--- Recent Trades (Last 5) ---")
        for i, trade in enumerate(report.trade_list[-5:], 1):
            lines.append(
                f"{i}. {trade.symbol} {trade.side.upper()}: "
                f"P&L ${trade.pnl:.2f} ({trade.pnl_percent*100:.2f}%)"
            )

    # Add anomalies
    if report.anomalies:
        lines.append(f"\n--- Detected Anomalies ({len(report.anomalies)}) ---")
        for i, anomaly in enumerate(report.anomalies, 1):
            lines.append(f"{i}. {anomaly}")

    lines.append("\n" + "=" * 40)

    return "\n".join(lines)


def create_claude_prompt_context(report: PerformanceReport) -> Dict[str, Any]:
    """
    Create context dictionary for Claude model prompts

    This provides structured data that can be easily inserted into prompts.

    Args:
        report: PerformanceReport object

    Returns:
        Dictionary with formatted context data
    """
    metrics = report.metrics

    return {
        "period": report.period,
        "total_trades": metrics.total_trades,
        "win_rate": f"{metrics.win_rate*100:.2f}%",
        "profit_factor": (
            "∞" if metrics.profit_factor == float("inf") else f"{metrics.profit_factor:.2f}"
        ),
        "max_drawdown": f"{metrics.max_drawdown*100:.2f}%",
        "sharpe_ratio": f"{metrics.sharpe_ratio:.2f}",
        "sortino_ratio": f"{metrics.sortino_ratio:.2f}",
        "total_pnl": f"${metrics.total_pnl:.2f}",
        "avg_win": f"${metrics.avg_win:.2f}",
        "avg_loss": f"${metrics.avg_loss:.2f}",
        "anomalies": report.anomalies,
        "anomaly_count": len(report.anomalies),
        "formatted_report": format_for_claude(report),
    }
