# retoor <retoor@molodetz.nl>

from __future__ import annotations

import time

from devplacepy.database import db
from devplacepy.services.base import BaseService
from devplacepy.services.pubsub import publish as pubsub_publish

from . import store

BATCH_LIMIT = 500
SWEEP_SECONDS = 60


def battle_topic(war_uid: str) -> str:
    return f"public.battle.{war_uid}"


class OpinionWarService(BaseService):
    title = "Opinion Wars"
    description = (
        "Relays persisted battle events onto the pub/sub bus for live cards, resolves "
        "ended wars that nobody viewed, and sends the fight-cooldown-ready "
        "notifications. Runs on the service lock owner, where every pub/sub "
        "subscriber converges; the event table stays the source of truth."
    )
    default_enabled = True

    def __init__(self):
        super().__init__(name="opinionwar", interval_seconds=2)
        self._watermark = 0
        self._primed = False
        self._last_sweep = 0.0

    def _max_id(self) -> int:
        if "opinion_war_events" not in db.tables:
            return 0
        rows = list(db.query("SELECT MAX(id) AS max_id FROM opinion_war_events"))
        value = rows[0]["max_id"] if rows else None
        return int(value or 0)

    async def _relay_events(self) -> None:
        if "opinion_war_events" not in db.tables:
            return
        if not self._primed:
            self._watermark = self._max_id()
            self._primed = True
            return
        rows = list(
            db.query(
                "SELECT * FROM opinion_war_events WHERE id > :wm "
                "ORDER BY id ASC LIMIT :lim",
                wm=self._watermark,
                lim=BATCH_LIMIT,
            )
        )
        if not rows:
            return
        delivered = 0
        for row in rows:
            delivered += await pubsub_publish(
                battle_topic(row["war_uid"]), store._event_dict(dict(row))
            )
        self._watermark = max(row["id"] for row in rows)
        if delivered:
            self.log(f"relayed {len(rows)} battle event(s), {delivered} live frame(s)")

    def _sweep(self) -> None:
        now = time.monotonic()
        if now - self._last_sweep < SWEEP_SECONDS:
            return
        self._last_sweep = now
        resolved = store.resolve_due_wars()
        if resolved:
            self.log(f"resolved {resolved} ended war(s)")
        notified = 0
        for fighter in store.cooldown_ready_fighters():
            if store.notify_cooldown_ready(fighter):
                notified += 1
        if notified:
            self.log(f"sent {notified} fight-ready notification(s)")

    async def run_once(self) -> None:
        await self._relay_events()
        self._sweep()

    def collect_metrics(self) -> dict:
        return {"watermark": self._watermark, "primed": self._primed}
