"""
Markdown report generation module.

This module generates professional markdown reports from backtest results,
suitable for documentation, sharing, or archiving.
"""

from datetime import datetime
from pathlib import Path

from jbqlab.types import BacktestResult


def generate_report(
    result: BacktestResult,
    output_path: str | Path | None = None,
    title: str = "Backtest Report",
    include_equity_plot: bool = True,
) -> str:
    """Generate a markdown report from backtest results.

    Args:
        result: BacktestResult from run_backtest.
        output_path: Optional path to save the report. If None, returns string only.
        title: Report title.
        include_equity_plot: Whether to include equity plot reference.

    Returns:
        Markdown report as a string.
    """
    metadata = result.metadata
    metrics = result.metrics

    # Build report sections
    sections = []

    # Header
    sections.append(f"# {title}")
    sections.append("")
    sections.append(f"*Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*")
    sections.append("")

    # Summary
    sections.append("## Summary")
    sections.append("")
    sections.append(f"- **Strategy**: {metadata.get('strategy', 'N/A')}")
    sections.append(f"- **Data Source**: {metadata.get('data_source', 'N/A')}")
    sections.append(f"- **Period**: {metadata.get('start_date', 'N/A')[:10]} to {metadata.get('end_date', 'N/A')[:10]}")
    sections.append(f"- **Trading Days**: {metadata.get('num_days', 'N/A')}")
    sections.append(f"- **Initial Capital**: ${metadata.get('initial_capital', 100000):,.2f}")
    sections.append("")

    # Strategy Parameters
    strategy_params = metadata.get("strategy_params", {})
    if strategy_params:
        sections.append("### Strategy Parameters")
        sections.append("")
        sections.append("| Parameter | Value |")
        sections.append("|-----------|-------|")
        for param, value in strategy_params.items():
            sections.append(f"| {param} | {value} |")
        sections.append("")

    # Cost Model
    sections.append("### Cost Model")
    sections.append("")
    sections.append(f"- **Transaction Cost**: {metadata.get('transaction_cost', 0) * 100:.2f}%")
    sections.append(f"- **Slippage**: {metadata.get('slippage', 0) * 100:.2f}%")
    sections.append("")

    # Performance Metrics
    sections.append("## Performance Metrics")
    sections.append("")
    sections.append("| Metric | Value |")
    sections.append("|--------|-------|")

    # Format each metric appropriately
    metric_formats = {
        "total_return": ("Total Return", lambda x: f"{x * 100:+.2f}%"),
        "cagr": ("CAGR", lambda x: f"{x * 100:+.2f}%"),
        "volatility": ("Volatility (Ann.)", lambda x: f"{x * 100:.2f}%"),
        "sharpe": ("Sharpe Ratio", lambda x: f"{x:.2f}"),
        "sortino": ("Sortino Ratio", lambda x: f"{x:.2f}"),
        "max_drawdown": ("Max Drawdown", lambda x: f"{x * 100:.2f}%"),
        "calmar": ("Calmar Ratio", lambda x: f"{x:.2f}"),
    }

    for key, (name, formatter) in metric_formats.items():
        if key in metrics:
            value = metrics[key]
            if isinstance(value, float) and abs(value) != float("inf"):
                sections.append(f"| {name} | {formatter(value)} |")
            else:
                sections.append(f"| {name} | {value} |")

    sections.append("")

    # Performance Interpretation
    sections.append("## Performance Analysis")
    sections.append("")

    sharpe = metrics.get("sharpe", 0)
    if sharpe > 2:
        sharpe_interp = "Excellent risk-adjusted returns"
    elif sharpe > 1:
        sharpe_interp = "Good risk-adjusted returns"
    elif sharpe > 0.5:
        sharpe_interp = "Moderate risk-adjusted returns"
    elif sharpe > 0:
        sharpe_interp = "Low risk-adjusted returns"
    else:
        sharpe_interp = "Negative risk-adjusted returns"

    max_dd = metrics.get("max_drawdown", 0)
    if max_dd < 0.1:
        dd_interp = "Low drawdown risk"
    elif max_dd < 0.2:
        dd_interp = "Moderate drawdown risk"
    elif max_dd < 0.3:
        dd_interp = "Elevated drawdown risk"
    else:
        dd_interp = "High drawdown risk"

    sections.append(f"- **Risk-Adjusted Performance**: {sharpe_interp} (Sharpe: {sharpe:.2f})")
    sections.append(f"- **Drawdown Risk**: {dd_interp} (Max DD: {max_dd * 100:.1f}%)")
    sections.append("")

    # Equity Curve
    if include_equity_plot:
        sections.append("## Equity Curve")
        sections.append("")
        sections.append("![Equity Curve](equity_curve.png)")
        sections.append("")

    # Final Portfolio Value
    final_equity = result.equity_curve.iloc[-1]
    initial_capital = metadata.get("initial_capital", 100000)
    profit_loss = final_equity - initial_capital

    sections.append("## Final Results")
    sections.append("")
    sections.append(f"- **Final Portfolio Value**: ${final_equity:,.2f}")
    sections.append(f"- **Profit/Loss**: ${profit_loss:+,.2f}")
    sections.append("")

    # Footer
    sections.append("---")
    sections.append("")
    sections.append("*Report generated by [jbqlab](https://github.com/JaiAnshSB26/jbqlab) v0.1.0*")

    report = "\n".join(sections)

    # Save if path provided
    if output_path is not None:
        output_path = Path(output_path)
        output_path.parent.mkdir(parents=True, exist_ok=True)
        output_path.write_text(report, encoding="utf-8")

    return report


def generate_comparison_report(
    results: dict[str, BacktestResult],
    output_path: str | Path | None = None,
    title: str = "Strategy Comparison Report",
) -> str:
    """Generate a comparison report for multiple backtest results.

    Args:
        results: Dictionary mapping strategy names to BacktestResult objects.
        output_path: Optional path to save the report.
        title: Report title.

    Returns:
        Markdown report as a string.
    """
    sections = []

    # Header
    sections.append(f"# {title}")
    sections.append("")
    sections.append(f"*Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*")
    sections.append("")

    # Comparison Table
    sections.append("## Performance Comparison")
    sections.append("")

    # Build header
    header = "| Metric |"
    separator = "|--------|"
    for name in results:
        header += f" {name} |"
        separator += "--------|"

    sections.append(header)
    sections.append(separator)

    # Metrics to compare
    metrics_to_compare = [
        ("Total Return", "total_return", lambda x: f"{x * 100:+.2f}%"),
        ("CAGR", "cagr", lambda x: f"{x * 100:+.2f}%"),
        ("Sharpe", "sharpe", lambda x: f"{x:.2f}"),
        ("Sortino", "sortino", lambda x: f"{x:.2f}"),
        ("Volatility", "volatility", lambda x: f"{x * 100:.2f}%"),
        ("Max Drawdown", "max_drawdown", lambda x: f"{x * 100:.2f}%"),
        ("Calmar", "calmar", lambda x: f"{x:.2f}"),
    ]

    for display_name, metric_key, formatter in metrics_to_compare:
        row = f"| {display_name} |"
        for result in results.values():
            value = result.metrics.get(metric_key, 0)
            if isinstance(value, float) and abs(value) != float("inf"):
                row += f" {formatter(value)} |"
            else:
                row += f" {value} |"
        sections.append(row)

    sections.append("")

    # Winner summary
    sections.append("## Summary")
    sections.append("")

    # Find best Sharpe
    best_sharpe_name = max(results.keys(), key=lambda k: results[k].metrics.get("sharpe", float("-inf")))
    best_sharpe = results[best_sharpe_name].metrics.get("sharpe", 0)

    # Find best return
    best_return_name = max(results.keys(), key=lambda k: results[k].metrics.get("total_return", float("-inf")))
    best_return = results[best_return_name].metrics.get("total_return", 0)

    sections.append(f"- **Best Risk-Adjusted (Sharpe)**: {best_sharpe_name} ({best_sharpe:.2f})")
    sections.append(f"- **Best Total Return**: {best_return_name} ({best_return * 100:+.2f}%)")
    sections.append("")

    # Footer
    sections.append("---")
    sections.append("")
    sections.append("*Report generated by [jbqlab](https://github.com/JaiAnshSB26/jbqlab) v0.1.0*")

    report = "\n".join(sections)

    if output_path is not None:
        output_path = Path(output_path)
        output_path.parent.mkdir(parents=True, exist_ok=True)
        output_path.write_text(report, encoding="utf-8")

    return report
