#!/usr/bin/env python3
"""
patch_forecast_alerts.py — the server fires the Telegram forecast alert
after each successful rollover build.

Run AFTER patch_forecast_page.py. Save to the project root:
    cd C:\\Users\\Administrator\\OneDrive\\fx_macro_intraday
    python patch_forecast_alerts.py

Change to dashboard_server.py: after build_forecast.py exits cleanly,
run notify_forecast.py (which itself sends only once per session).

Safety: backup (.bak_alerts_<timestamp>), exact-match verify, syntax
check, re-runnable.
"""

import py_compile
import shutil
import sys
import time
from pathlib import Path

ROOT = Path(__file__).resolve().parent
SERVER = ROOT / "src" / "execution" / "dashboard_server.py"

PATCHES = [
    {
        "label": "add FORECAST_NOTIFY_SCRIPT constant",
        "old": 'FORECAST_LOG    = BASE_PATH / "data" / "logs" / "forecast_build.log"',
        "new": 'FORECAST_LOG    = BASE_PATH / "data" / "logs" / "forecast_build.log"\n'
               'FORECAST_NOTIFY_SCRIPT = BASE_PATH / "src" / "execution" / "notify_forecast.py"',
        "marker": "FORECAST_NOTIFY_SCRIPT = ",
        "anchor": "FORECAST_LOG",
    },
    {
        "label": "run the notifier after a clean build",
        "old": '                    stderr=subprocess.STDOUT, timeout=300,\n'
               '                )\n'
               '            print(f"  [forecast] build finished (exit {r.returncode})")',
        "new": '                    stderr=subprocess.STDOUT, timeout=300,\n'
               '                )\n'
               '                if r.returncode == 0 and FORECAST_NOTIFY_SCRIPT.exists():\n'
               '                    subprocess.run(\n'
               '                        [sys.executable, str(FORECAST_NOTIFY_SCRIPT)],\n'
               '                        cwd=str(BASE_PATH), stdout=lf,\n'
               '                        stderr=subprocess.STDOUT, timeout=90,\n'
               '                    )\n'
               '            print(f"  [forecast] build finished (exit {r.returncode})")',
        "marker": "FORECAST_NOTIFY_SCRIPT.exists()",
        "anchor": "timeout=300",
    },
]


def read_raw(path):
    with open(path, "r", encoding="utf-8", newline="") as f:
        return f.read()


def write_raw(path, text):
    with open(path, "w", encoding="utf-8", newline="") as f:
        f.write(text)


def dump_region(text, anchor):
    i = text.find(anchor)
    if i == -1:
        print(f"    (anchor {anchor!r} not found either — file layout differs)")
        return
    print("    Exact bytes around anchor (repr):")
    print("    " + repr(text[max(0, i - 80):i + 320]))


def main():
    print("=" * 62)
    print("FORECAST TELEGRAM ALERTS PATCHER")
    print(f"  Root: {ROOT}")
    print("=" * 62)

    if not SERVER.exists():
        sys.exit(f"FAIL: {SERVER} not found — run from the project root.")
    if "def maybe_refresh_forecast" not in read_raw(SERVER):
        sys.exit("FAIL: forecast-page patch not applied yet — run "
                 "patch_forecast_page.py first.")
    nf = ROOT / "src" / "execution" / "notify_forecast.py"
    if not nf.exists():
        print("  NOTE: notify_forecast.py not found yet — save it to "
              "src\\execution\\ before restarting the server.")

    ts = time.strftime("%Y%m%d_%H%M%S")
    failures = 0
    changed = False
    backed_up = False

    for spec in PATCHES:
        print(f"\n[{SERVER.name}] {spec['label']}")
        text = read_raw(SERVER)
        nl = "\r\n" if "\r\n" in text else "\n"
        old = spec["old"].replace("\r\n", "\n").replace("\n", nl)
        new = spec["new"].replace("\r\n", "\n").replace("\n", nl)

        if spec["marker"] in text:
            print("  OK: already patched — skipping.")
            continue

        n = text.count(old)
        if n != 1:
            print(f"  FAIL: expected exactly 1 match, found {n}.")
            dump_region(text, spec["anchor"])
            failures += 1
            continue

        if not backed_up:
            backup = SERVER.with_name(SERVER.name + f".bak_alerts_{ts}")
            shutil.copy2(SERVER, backup)
            backed_up = True
            print(f"  Backup: {backup.name}")

        write_raw(SERVER, text.replace(old, new, 1))
        if spec["marker"] not in read_raw(SERVER):
            print("  FAIL: post-write verification failed — check backup.")
            failures += 1
            continue
        print("  Patched OK.")
        changed = True

    if changed:
        try:
            py_compile.compile(str(SERVER), doraise=True)
            print(f"\n[{SERVER.name}] Syntax check OK.")
        except Exception as e:
            print(f"\n[{SERVER.name}] SYNTAX CHECK FAILED: {e}")
            print("  Restore from the .bak_alerts file and send me this output.")
            failures += 1

    print("\n" + "=" * 62)
    if failures:
        print(f"DONE WITH {failures} FAILURE(S) — send me the full output above.")
        sys.exit(1)
    print("ALL PATCHES APPLIED.")
    print("Next steps:")
    print("  1. Save notify_forecast.py to src\\execution\\")
    print("  2. Test to yourself only:")
    print("       python src\\execution\\notify_forecast.py --to YOUR_CHAT_ID")
    print("     (your chat id = TELEGRAM_CHAT_ID near the top of "
          "live_signal_monitor_v3.py)")
    print("  3. Restart the dashboard server.")
    print("     From the next rollover, everyone gets the forecast + their")
    print("     personal dashboard link automatically, once per session.")
    print("=" * 62)


if __name__ == "__main__":
    main()
