#!/usr/bin/env python3
"""Same-Pi EtherGold → DyzineFrame fireworks trigger (atomic JSON file, no HTTP loopback)."""

from __future__ import annotations

import json
import os
import tempfile
import time
from datetime import datetime, timezone
from typing import Any

FIREWORKS_REQUEST_NAME = "fireworks-request.json"
DEFAULT_ETHERGOLD_ROOT = "/home/topbox/EtherGold"

# Legacy bell: ringbell(50) winner, ringbell(20) bank — mapped to display seconds.
DEFAULT_WINNER_DURATION_SEC = 60.0
DEFAULT_BANK_DURATION_SEC = 30.0


def resolve_ethergold_root() -> str:
    return os.environ.get("ETHERGOLD_ROOT", DEFAULT_ETHERGOLD_ROOT).strip() or DEFAULT_ETHERGOLD_ROOT


def resolve_fireworks_request_path() -> str:
    explicit = os.environ.get("ETHERGOLD_FIREWORKS_REQUEST_PATH", "").strip()
    if explicit:
        return explicit
    return os.path.join(resolve_ethergold_root(), FIREWORKS_REQUEST_NAME)


def resolve_local_wire_tid() -> str:
    """Optional override only — bridge passes learned UART TID into write_fireworks_request."""
    return os.environ.get("ETHERGOLD_LOCAL_WIRE_TID", "").strip().upper()


def _env_float(name: str, default: float) -> float:
    raw = os.environ.get(name, "").strip()
    if not raw:
        return default
    try:
        return float(raw)
    except ValueError:
        return default


def fireworks_duration_sec(*, winner_tid: str, local_wire_tid: str | None = None) -> float:
    """Winner machine = long celebration; all other bank Topboxes = short (mirrors bell split)."""
    winner = (winner_tid or "").strip().upper()
    local = (local_wire_tid if local_wire_tid is not None else resolve_local_wire_tid()).strip().upper()
    winner_sec = _env_float("ETHERGOLD_FIREWORKS_WINNER_SEC", DEFAULT_WINNER_DURATION_SEC)
    bank_sec = _env_float("ETHERGOLD_FIREWORKS_BANK_SEC", DEFAULT_BANK_DURATION_SEC)
    if winner and local and winner == local:
        return max(1.0, winner_sec)
    return max(1.0, bank_sec)


def write_fireworks_request(
    *,
    winner_tid: str,
    progwin_cents: int,
    game_id_hex: str | None = None,
    dedupe_key: str | None = None,
    local_wire_tid: str | None = None,
    is_progressive: bool = True,
) -> dict[str, Any]:
    """Atomically publish fireworks-request.json beside progressives.csv.

    ``is_progressive`` distinguishes a bank progressive jackpot (Phase 1 — full
    celebration with the JACKPOT WINNER amount overlay, duration-based loop) from a
    local slot cash win (Phase 2 — single loop, no amount overlay). Older writers
    omit the flag; the reader treats a missing flag as progressive.
    """
    duration_sec = fireworks_duration_sec(winner_tid=winner_tid, local_wire_tid=local_wire_tid)
    path = resolve_fireworks_request_path()
    parent = os.path.dirname(path) or "."
    os.makedirs(parent, exist_ok=True)
    seq = int(time.time() * 1000) % 1_000_000_000
    payload: dict[str, Any] = {
        "seq": seq,
        "updated_utc": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
        "winner_tid": winner_tid.upper(),
        "duration_sec": duration_sec,
        "winner_duration_sec": _env_float(
            "ETHERGOLD_FIREWORKS_WINNER_SEC", DEFAULT_WINNER_DURATION_SEC
        ),
        "bank_duration_sec": _env_float(
            "ETHERGOLD_FIREWORKS_BANK_SEC", DEFAULT_BANK_DURATION_SEC
        ),
        "progwin_cents": int(progwin_cents),
        "is_progressive": bool(is_progressive),
    }
    if game_id_hex:
        payload["game_id_hex"] = game_id_hex
    if dedupe_key:
        payload["dedupe_key"] = dedupe_key
    local = (local_wire_tid if local_wire_tid is not None else resolve_local_wire_tid()).strip()
    if local:
        payload["local_wire_tid"] = local.upper()
        payload["is_winner"] = winner_tid.upper() == local.upper()
    fd, tmp_path = tempfile.mkstemp(
        dir=parent,
        prefix=".fireworks-request.",
        suffix=".tmp",
    )
    try:
        with os.fdopen(fd, "w", encoding="utf-8") as handle:
            json.dump(payload, handle, separators=(",", ":"))
            handle.write("\n")
        os.replace(tmp_path, path)
        try:
            os.chmod(path, 0o644)
            real_user = os.environ.get("ETHERGOLD_REAL_USER", "topbox")
            import pwd

            pw = pwd.getpwnam(real_user)
            os.chown(path, pw.pw_uid, pw.pw_gid)
        except (OSError, KeyError, ImportError):
            try:
                os.chmod(path, 0o644)
            except OSError:
                pass
    except Exception:
        try:
            os.unlink(tmp_path)
        except OSError:
            pass
        raise
    return payload


def local_fireworks_ipc_enabled() -> bool:
    raw = os.environ.get("ETHERGOLD_FIREWORKS_IPC", "1").strip().lower()
    return raw not in ("0", "false", "no", "off")


def read_fireworks_request(path: str | None = None) -> dict[str, Any] | None:
    target = path or resolve_fireworks_request_path()
    if not os.path.isfile(target):
        return None
    try:
        with open(target, encoding="utf-8") as handle:
            payload = json.load(handle)
        if isinstance(payload, dict):
            return payload
    except (OSError, ValueError, json.JSONDecodeError):
        pass
    return None
