"""
MT5 ストラテジーテスターが保存した HTML から window.__report を読み、Balance/Equity 風 PNG を出すサンプル。
MT5 への接続は不要（本サイト MT5×Python #4 用ダウンロード版）。

同じフォルダに mt5_report_extract.py を置いてから実行してください。
GitHub 利用者はリポジトリの scripts/research と同等の配置でも動きます。
"""
from __future__ import annotations

import argparse
import json
import sys
from datetime import datetime, timezone
from pathlib import Path

import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import numpy as np

_here = Path(__file__).resolve().parent
if str(_here) not in sys.path:
    sys.path.insert(0, str(_here))

from mt5_report_extract import extract_report_dict_from_html  # noqa: E402


def _extract_report_json(html_path: str):
    return extract_report_dict_from_html(html_path)


def generate_chart_from_report(html_path: str, output_path: str, title: str | None = None) -> None:
    report = _extract_report_json(html_path)

    balance_data = report.get("balance", {})
    chart_points = balance_data.get("chart", [])
    account = report.get("account", {})
    indicators = report.get("summaryIndicators", {})
    currency = account.get("currency", "JPY")

    if not chart_points:
        print("No chart data found in report.")
        return

    timestamps = [datetime.fromtimestamp(p["x"], tz=timezone.utc) for p in chart_points]
    balances = [p["y"][0] for p in chart_points]
    equities = [p["y"][1] for p in chart_points]

    final_balance = balance_data.get("balance", balances[-1] if balances else 0)
    max_dd_pct = indicators.get("drawdown", 0) * 100
    profit_factor = indicators.get("profit_factor", 0)

    plt.rcParams.update(
        {
            "font.family": "sans-serif",
            "font.sans-serif": ["Segoe UI", "Arial", "Helvetica", "Meiryo"],
            "font.size": 9,
            "axes.unicode_minus": False,
        }
    )

    fig, ax = plt.subplots(figsize=(10, 5), dpi=150)
    fig.patch.set_facecolor("#FFFFFF")
    ax.set_facecolor("#F8F8F8")

    ax.plot(
        timestamps,
        balances,
        color="#2196F3",
        linewidth=1.8,
        label="Balance",
        zorder=3,
        solid_capstyle="round",
    )
    ax.plot(
        timestamps,
        equities,
        color="#4CAF50",
        linewidth=1.2,
        label="Equity",
        zorder=2,
        alpha=0.85,
    )

    balance_arr = np.array(balances)
    equity_arr = np.array(equities)
    dd_mask = equity_arr < balance_arr
    if np.any(dd_mask):
        ax.fill_between(
            timestamps,
            balances,
            equities,
            where=dd_mask,
            interpolate=True,
            color="#F44336",
            alpha=0.12,
            zorder=1,
            label="Drawdown",
        )

    ax.grid(True, which="major", linestyle="-", linewidth=0.3, color="#CCCCCC", alpha=0.7)
    ax.grid(True, which="minor", linestyle=":", linewidth=0.2, color="#E0E0E0", alpha=0.5)
    ax.minorticks_on()

    ax.spines["top"].set_visible(False)
    for side in ["right", "left", "bottom"]:
        ax.spines[side].set_color("#BBBBBB")
        ax.spines[side].set_linewidth(0.5)

    ax.xaxis.set_major_formatter(mdates.DateFormatter("%m/%d"))
    ax.xaxis.set_major_locator(mdates.AutoDateLocator(minticks=4, maxticks=10))
    plt.setp(ax.xaxis.get_majorticklabels(), rotation=0, ha="center", fontsize=8, color="#555555")

    def currency_fmt(x, pos):
        if currency == "JPY":
            return f"¥{x:,.0f}"
        return f"{x:,.2f}"

    ax.yaxis.set_major_formatter(mticker.FuncFormatter(currency_fmt))
    plt.setp(ax.yaxis.get_majorticklabels(), fontsize=8, color="#555555")
    ax.yaxis.set_label_position("right")
    ax.yaxis.tick_right()

    y_min = min(min(balances), min(equities))
    y_max = max(max(balances), max(equities))
    y_margin = (y_max - y_min) * 0.15 if y_max != y_min else y_max * 0.02
    ax.set_ylim(y_min - y_margin, y_max + y_margin * 1.5)

    last_ts = timestamps[-1]
    ax.annotate(
        f"¥{final_balance:,.0f}" if currency == "JPY" else f"{final_balance:,.2f}",
        xy=(last_ts, final_balance),
        xytext=(8, 8),
        textcoords="offset points",
        fontsize=9,
        fontweight="bold",
        color="#2196F3",
        bbox=dict(
            boxstyle="round,pad=0.3",
            facecolor="white",
            edgecolor="#2196F3",
            alpha=0.9,
            linewidth=0.8,
        ),
        zorder=5,
    )

    profit_total = final_balance - balances[0]
    profit_sign = "+" if profit_total >= 0 else ""
    stats_text = (
        f"Profit: {profit_sign}¥{profit_total:,.0f}\nDD: {max_dd_pct:.2f}%\nPF: {profit_factor:.2f}"
        if currency == "JPY"
        else f"Profit: {profit_sign}{profit_total:,.2f}\nDD: {max_dd_pct:.2f}%\nPF: {profit_factor:.2f}"
    )
    props = dict(boxstyle="round,pad=0.5", facecolor="white", edgecolor="#CCCCCC", alpha=0.92, linewidth=0.6)
    ax.text(
        0.015,
        0.97,
        stats_text,
        transform=ax.transAxes,
        fontsize=8,
        verticalalignment="top",
        fontfamily="monospace",
        color="#333333",
        bbox=props,
    )

    legend = ax.legend(
        loc="upper center",
        ncol=3,
        frameon=True,
        fontsize=8,
        edgecolor="#CCCCCC",
        fancybox=True,
        framealpha=0.92,
    )
    legend.get_frame().set_linewidth(0.5)

    if title is None:
        title = "Balance / Equity"
    ax.set_title(title, fontsize=11, fontweight="bold", color="#333333", pad=12, loc="left")

    plt.tight_layout()
    fig.savefig(output_path, dpi=150, bbox_inches="tight", facecolor="#FFFFFF", edgecolor="none")
    plt.close(fig)
    print(f"MT5-style chart saved: {output_path}")


def main() -> int:
    p = argparse.ArgumentParser(description="HTML report -> Balance/Equity PNG (no MT5 connection)")
    p.add_argument("--chart-from-html", metavar="HTML_PATH", required=True, help="ReportTester HTML")
    p.add_argument("-o", "--out", metavar="PNG_PATH", help="Output PNG (default: same folder, _chart.png)")
    args = p.parse_args()
    html_path = args.chart_from_html
    if args.out:
        out_path = args.out
    else:
        out_path = html_path.replace(".html", "_chart.png")
    try:
        generate_chart_from_report(html_path, out_path)
    except (ValueError, OSError, json.JSONDecodeError) as e:
        print(e, file=sys.stderr)
        return 1
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
