"""
Reporting module.

This module handles saving backtest results to files:
- metrics.json
- equity_curve.csv
- positions.csv
"""

import json
from pathlib import Path

import pandas as pd

from jbqlab.types import BacktestResult

# =============================================================================
# Public API
# =============================================================================


def save_results(
    result: BacktestResult,
    output_dir: str | Path,
    prefix: str = "",
) -> dict[str, Path]:
    """Save backtest results to files.

    Creates the following files in output_dir:
    - metrics.json: Performance metrics and metadata
    - equity_curve.csv: Daily equity values
    - positions.csv: Daily position signals

    Args:
        result: BacktestResult from run_backtest.
        output_dir: Directory to save files to.
        prefix: Optional prefix for filenames (e.g., "sma_" -> "sma_metrics.json").

    Returns:
        Dictionary mapping file type to Path of saved file.
    """
    output_dir = Path(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    saved_files: dict[str, Path] = {}

    # Save metrics.json
    metrics_path = output_dir / f"{prefix}metrics.json"
    save_metrics(result, metrics_path)
    saved_files["metrics"] = metrics_path

    # Save equity_curve.csv
    equity_path = output_dir / f"{prefix}equity_curve.csv"
    save_equity_curve(result, equity_path)
    saved_files["equity_curve"] = equity_path

    # Save positions.csv
    positions_path = output_dir / f"{prefix}positions.csv"
    save_positions(result, positions_path)
    saved_files["positions"] = positions_path

    return saved_files


def save_metrics(result: BacktestResult, path: str | Path) -> None:
    """Save metrics and metadata to JSON file.

    Args:
        result: BacktestResult from run_backtest.
        path: Path to save JSON file.
    """
    path = Path(path)
    path.parent.mkdir(parents=True, exist_ok=True)

    output = {
        "metrics": result.metrics,
        "metadata": result.metadata,
    }

    with open(path, "w", encoding="utf-8") as f:
        json.dump(output, f, indent=2, default=str)


def save_equity_curve(result: BacktestResult, path: str | Path) -> None:
    """Save equity curve to CSV file.

    Args:
        result: BacktestResult from run_backtest.
        path: Path to save CSV file.
    """
    path = Path(path)
    path.parent.mkdir(parents=True, exist_ok=True)

    df = pd.DataFrame(
        {
            "date": result.equity_curve.index,
            "equity": result.equity_curve.values,
            "return": result.returns.values,
        }
    )
    df.to_csv(path, index=False)


def save_positions(result: BacktestResult, path: str | Path) -> None:
    """Save positions to CSV file.

    Args:
        result: BacktestResult from run_backtest.
        path: Path to save CSV file.
    """
    path = Path(path)
    path.parent.mkdir(parents=True, exist_ok=True)

    df = pd.DataFrame(
        {
            "date": result.positions.index,
            "position": result.positions.values,
        }
    )
    df.to_csv(path, index=False)


def format_metrics_table(metrics: dict[str, float]) -> str:
    """Format metrics as a human-readable table.

    Args:
        metrics: Dictionary of metric name -> value.

    Returns:
        Formatted string table.
    """
    lines = ["┌─────────────────┬──────────────┐", "│ Metric          │ Value        │", "├─────────────────┼──────────────┤"]

    for name, value in metrics.items():
        # Format value based on metric type
        if name in ("total_return", "cagr", "volatility", "max_drawdown"):
            formatted = f"{value * 100:>10.2f}%"
        elif name in ("sharpe", "sortino", "calmar"):
            formatted = f"{value:>11.2f}"
        else:
            formatted = f"{value:>12.4f}"

        lines.append(f"│ {name:<15} │ {formatted} │")

    lines.append("└─────────────────┴──────────────┘")

    return "\n".join(lines)
