import csv
import re
from pathlib import Path


ROOT = Path(r"C:\Users\user\Documents\New project\KOUCHA_GOLD_GLOBAL_MARKET_CLOSED_RETRY_COMPARE")
MANIFEST = ROOT / "test_manifest.csv"


def read_csv(path):
    if not path.exists():
        return []
    with path.open("r", encoding="utf-8-sig", newline="") as f:
        return list(csv.DictReader(f))


def write_csv(path, rows, fields=None):
    if fields is None and rows:
        fields = list(rows[0].keys())
    with path.open("w", encoding="utf-8-sig", newline="") as f:
        if not fields:
            return
        w = csv.DictWriter(f, fieldnames=fields)
        w.writeheader()
        w.writerows(rows)


def num(row, key, default=0.0):
    try:
        value = row.get(key, "")
        if value == "":
            return default
        return float(value)
    except Exception:
        return default


def count(rows, event):
    return sum(1 for r in rows if r.get("EventType") == event)


def sum_profit(rows, event):
    return sum(num(r, "ProfitYen") for r in rows if r.get("EventType") == event)


def final_balance_from_log(path):
    if not path.exists():
        return "", "", ""
    for enc in ("utf-16", "utf-8", "cp932"):
        try:
            text = path.read_text(encoding=enc, errors="ignore")
            break
        except Exception:
            text = ""
    lines = text.splitlines()
    run_start = 0
    initial = ""
    for i, line in enumerate(lines):
        if "initial deposit 50000 JPY, leverage 1:888" in line:
            run_start = i
            initial = line
    run_text = "\n".join(lines[run_start:]) if lines else text
    final = ""
    equity = ""
    for match in re.finditer(r"final balance ([0-9.-]+) JPY", run_text):
        final = match.group(1)
    for match in re.finditer(r"final balance [0-9.-]+ JPY, equity ([0-9.-]+)", run_text):
        equity = match.group(1)
    return final, equity, initial


def run_elapsed_seconds(test_name):
    rows = read_csv(ROOT / "run_status.csv")
    vals = [r for r in rows if r.get("TestName") == test_name and r.get("Phase") == "END"]
    return vals[-1].get("ElapsedSeconds", "") if vals else ""


def drawdown_from_events(rows):
    peak = None
    max_dd = 0.0
    max_dd_pct = 0.0
    for row in rows:
        equity = num(row, "Equity", None)
        if equity is None:
            continue
        if peak is None or equity > peak:
            peak = equity
        dd = peak - equity
        if dd > max_dd:
            max_dd = dd
            max_dd_pct = dd / peak * 100.0 if peak else 0.0
    return max_dd, max_dd_pct


def profit_factor(rows):
    close_events = [r for r in rows if r.get("EventType", "").endswith("CLOSE")]
    profits = [num(r, "ProfitYen") for r in close_events]
    gp = sum(x for x in profits if x > 0)
    gl = -sum(x for x in profits if x < 0)
    if gl <= 0:
        return 999.0 if gp > 0 else 0.0
    return gp / gl


def events_in(rows, names):
    names = set(names)
    return [r for r in rows if r.get("EventType") in names]


def close_sequence(rows):
    return [
        (
            r.get("TesterTime", ""),
            r.get("EventType", ""),
            r.get("Direction", ""),
            round(num(r, "ProfitYen"), 2),
        )
        for r in rows
        if r.get("EventType", "").endswith("CLOSE")
    ]


def entry_sequence(rows):
    return [
        (
            r.get("TesterTime", ""),
            r.get("EventType", ""),
            r.get("Direction", ""),
            r.get("Price", ""),
        )
        for r in rows
        if r.get("EventType") in ("ENTRY_BUY", "ENTRY_SELL", "DEFENSE_HEDGE_BUY", "DEFENSE_HEDGE_SELL")
    ]


def main():
    manifest = read_csv(MANIFEST)
    summaries = []
    retry_events = []
    close_intents = []
    blocked_entries = []
    sequences = {}

    for test in manifest:
        test_name = test["TestName"]
        pattern = test["Pattern"]
        test_dir = ROOT / test_name
        events_path = test_dir / f"{test_name}_trade_events.csv"
        log_path = test_dir / f"{test_name}_tester.log"
        events = read_csv(events_path)
        final_balance, final_equity, initial_line = final_balance_from_log(log_path)
        if not final_balance:
            final_balance = str(events[-1].get("Balance", "")) if events else ""
        if not final_equity:
            final_equity = str(events[-1].get("Equity", "")) if events else ""
        net_profit = float(final_balance) - 50000.0 if final_balance not in ("", None) else 0.0
        max_dd, max_dd_pct = drawdown_from_events(events)
        retry_names = [
            "GLOBAL_CLOSE_RETRY_PENDING",
            "GLOBAL_CLOSE_RETRY_ATTEMPT",
            "GLOBAL_CLOSE_RETRY_SUCCESS",
            "GLOBAL_CLOSE_RETRY_TIMEOUT",
            "GLOBAL_CLOSE_RETRY_BLOCK_NEW_ENTRY",
        ]
        retry_rows = events_in(events, retry_names)
        for r in retry_rows:
            out = {"Pattern": pattern, "TestName": test_name}
            out.update(r)
            retry_events.append(out)
            if r.get("EventType") in ("GLOBAL_CLOSE_RETRY_PENDING", "GLOBAL_CLOSE_RETRY_ATTEMPT", "GLOBAL_CLOSE_RETRY_SUCCESS", "GLOBAL_CLOSE_RETRY_TIMEOUT"):
                close_intents.append(out)
            if r.get("EventType") == "GLOBAL_CLOSE_RETRY_BLOCK_NEW_ENTRY":
                blocked_entries.append(out)

        total_trades = len(entry_sequence(events))
        summary = {
            "Pattern": pattern,
            "FinalBalance": round(float(final_balance), 2) if final_balance else "",
            "FinalEquity": round(float(final_equity), 2) if final_equity else "",
            "NetProfit": round(net_profit, 2),
            "ProfitFactor": round(profit_factor(events), 3),
            "MaxDrawdown": round(max_dd, 2),
            "MaxDrawdownPercent": round(max_dd_pct, 3),
            "TotalTrades": total_trades,
            "BasketCloseCount": count(events, "BASKET_CLOSE"),
            "BasketCloseProfitTotal": round(sum_profit(events, "BASKET_CLOSE"), 2),
            "DefenseHedgeCount": count(events, "DEFENSE_HEDGE_BUY") + count(events, "DEFENSE_HEDGE_SELL"),
            "HedgedBasketTimeExitCount": count(events, "HEDGED_BASKET_TIME_EXIT_CLOSE"),
            "HedgedBasketTimeExitProfitTotal": round(sum_profit(events, "HEDGED_BASKET_TIME_EXIT_CLOSE"), 2),
            "BasketRecoveryCloseCount": count(events, "BASKET_RECOVERY_CLOSE"),
            "BasketRecoveryLossCutCount": count(events, "BASKET_RECOVERY_LOSSCUT_CLOSE"),
            "HardStopCount": count(events, "HARDSTOP_CLOSE"),
            "HardStopProfitTotal": round(sum_profit(events, "HARDSTOP_CLOSE"), 2),
            "GlobalCloseRetryPendingCount": count(events, "GLOBAL_CLOSE_RETRY_PENDING"),
            "GlobalCloseRetryAttemptCount": count(events, "GLOBAL_CLOSE_RETRY_ATTEMPT"),
            "GlobalCloseRetrySuccessCount": count(events, "GLOBAL_CLOSE_RETRY_SUCCESS"),
            "GlobalCloseRetryTimeoutCount": count(events, "GLOBAL_CLOSE_RETRY_TIMEOUT"),
            "GlobalCloseRetryBlockNewEntryCount": count(events, "GLOBAL_CLOSE_RETRY_BLOCK_NEW_ENTRY"),
            "NoMoneyOrderFailedCount": count(events, "NO_MONEY"),
            "OrderSendFailedCount": count(events, "ORDER_SEND_FAILED") + count(events, "ORDER_RETCODE_ERROR"),
            "RunElapsedSeconds": run_elapsed_seconds(test_name),
            "Comment": "",
        }
        summaries.append(summary)
        sequences[pattern] = {
            "entries": entry_sequence(events),
            "closes": close_sequence(events),
            "summary": summary,
        }

    if len(summaries) >= 2:
        base = sequences.get("R0_P0_BASE")
        r1 = sequences.get("R1_GlobalMarketClosedRetryOnly")
        if base and r1:
            diffs = []
            if base["summary"]["NetProfit"] != r1["summary"]["NetProfit"]:
                diffs.append("NetProfitChanged")
            if base["entries"] != r1["entries"]:
                diffs.append("EntrySequenceChanged")
            if base["closes"] != r1["closes"]:
                diffs.append("CloseSequenceChanged")
            comment = "same_sequence" if not diffs else "|".join(diffs)
            for s in summaries:
                if s["Pattern"] == "R1_GlobalMarketClosedRetryOnly":
                    s["Comment"] = comment
                elif s["Pattern"] == "R0_P0_BASE":
                    s["Comment"] = "base"

    fields = [
        "Pattern","FinalBalance","FinalEquity","NetProfit","ProfitFactor","MaxDrawdown","MaxDrawdownPercent",
        "TotalTrades","BasketCloseCount","BasketCloseProfitTotal","DefenseHedgeCount",
        "HedgedBasketTimeExitCount","HedgedBasketTimeExitProfitTotal","BasketRecoveryCloseCount",
        "BasketRecoveryLossCutCount","HardStopCount","HardStopProfitTotal","GlobalCloseRetryPendingCount",
        "GlobalCloseRetryAttemptCount","GlobalCloseRetrySuccessCount","GlobalCloseRetryTimeoutCount",
        "GlobalCloseRetryBlockNewEntryCount","NoMoneyOrderFailedCount","OrderSendFailedCount",
        "RunElapsedSeconds","Comment",
    ]
    write_csv(ROOT / "global_market_closed_retry_compare_summary.csv", summaries, fields)
    write_csv(ROOT / "global_market_closed_retry_event_list.csv", retry_events)
    write_csv(ROOT / "close_intent_state_log.csv", close_intents)
    write_csv(ROOT / "retry_blocked_entry_log.csv", blocked_entries)

    speed_rows = [
        {
            "Pattern": s["Pattern"],
            "RunElapsedSeconds": s["RunElapsedSeconds"],
            "RunElapsedMinutes": round(float(s["RunElapsedSeconds"]) / 60.0, 2) if str(s["RunElapsedSeconds"]).strip() else "",
            "NetProfit": s["NetProfit"],
            "GlobalCloseRetryPendingCount": s["GlobalCloseRetryPendingCount"],
            "GlobalCloseRetrySuccessCount": s["GlobalCloseRetrySuccessCount"],
            "Comment": s["Comment"],
        }
        for s in summaries
    ]
    write_csv(ROOT / "speed_compare_summary.csv", speed_rows)


if __name__ == "__main__":
    main()
