from __future__ import annotations

import argparse
import json
import signal
from datetime import datetime, timezone
from pathlib import Path
from threading import Event, Thread

from hanz_realtime.gateway import RealtimeGateway
from hanz_realtime.yahoo_provider import YahooPollingProvider
from hanz_radar.engine import OpportunityRadar
from hanz_radar.bridge import RadarDecisionBridge
from hanz_server.service import HanzRealtimeService
from hanz_server.store import SQLiteStateStore


def main() -> int:
    parser = argparse.ArgumentParser(
        description="HANZ Yahoo IDX Opportunity Radar"
    )

    parser.add_argument(
        "--symbols",
        default="BBCA.JK,BMRI.JK,BBRI.JK",
    )

    parser.add_argument(
        "--poll-seconds",
        type=int,
        default=60,
    )

    parser.add_argument(
        "--rank-seconds",
        type=int,
        default=60,
    )

    parser.add_argument(
        "--db",
        default="/home/opc/hanz-radar/runtime/hanz.sqlite3",
    )

    parser.add_argument(
        "--snapshot",
        default="/home/opc/hanz-radar/runtime/radar_snapshot.json",
    )

    args = parser.parse_args()

    symbols = [
        item.strip()
        for item in args.symbols.split(",")
        if item.strip()
    ]

    provider = YahooPollingProvider(
        symbols=symbols,
        market="BEI",
        poll_seconds=args.poll_seconds,
    )

    gateway = RealtimeGateway()
    radar = OpportunityRadar(max_results=25)
    bridge = RadarDecisionBridge(radar)

    service = HanzRealtimeService(
        store=SQLiteStateStore(args.db),
    )

    snapshot_path = Path(args.snapshot)
    stop = Event()

    def shutdown(*_):
        stop.set()
        print(
            json.dumps(
                {"event": "hanz-yahoo-stop"}
            ),
            flush=True,
        )

    signal.signal(signal.SIGINT, shutdown)
    signal.signal(signal.SIGTERM, shutdown)

    def rank_loop():
        while not stop.wait(args.rank_seconds):
            try:
                now = datetime.now(timezone.utc)

                states = list(
                    gateway.states.values()
                )

                snapshot = radar.evaluate(
                    states,
                    now=now,
                )

                snapshot_path.parent.mkdir(
                    parents=True,
                    exist_ok=True,
                )

                snapshot_path.write_text(
                    json.dumps(
                        snapshot.to_dict(),
                        ensure_ascii=False,
                        indent=2,
                    ),
                    encoding="utf-8",
                )

                print(
                    json.dumps(
                        {
                            "event": "radar-heartbeat",
                            "total": snapshot.total_symbols,
                            "candidates": len(
                                snapshot.active_signals
                            ),
                            "updated_at": now.isoformat(),
                        }
                    ),
                    flush=True,
                )

                for decision in bridge.decisions(
                    states,
                    now=now,
                ):
                    service.process_decision(
                        decision
                    )

            except Exception as exc:
                print(
                    json.dumps(
                        {
                            "event": "radar-error",
                            "error": str(exc),
                        }
                    ),
                    flush=True,
                )

    print(
        json.dumps(
            {
                "event": "hanz-yahoo-start",
                "symbols": symbols,
                "poll_seconds": args.poll_seconds,
                "rank_seconds": args.rank_seconds,
            }
        ),
        flush=True,
    )

    worker = Thread(
        target=rank_loop,
        daemon=True,
    )

    worker.start()

    try:
        for tick in provider.stream():
            if stop.is_set():
                break

            state = gateway.ingest(tick)

            print(
                json.dumps(
                    {
                        "event": "tick",
                        "symbol": tick.symbol,
                        "price": tick.price,
                        "volume": tick.volume,
                        "score": state.anomaly_score,
                        "timestamp": tick.timestamp.isoformat(),
                    }
                ),
                flush=True,
            )

    finally:
        stop.set()
        worker.join(timeout=2)

    return 0


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