from __future__ import annotations

import json
import time
from typing import Any


class HeartbeatReporter:
    def __init__(self, name: str, interval_sec: int = 30) -> None:
        self.name = name
        self.interval_sec = max(5, int(interval_sec))
        self._last = 0.0

    async def beat(
        self,
        pool,
        status: str = "running",
        current_job_id: int | None = None,
        meta: dict[str, Any] | None = None,
        force: bool = False,
    ) -> None:
        now = time.monotonic()
        if not force and now - self._last < self.interval_sec:
            return
        self._last = now
        try:
            async with pool.acquire() as conn:
                await conn.execute(
                    """
                    INSERT INTO worker_heartbeats(name, heartbeat_at, status, current_job_id, meta_json, updated_at)
                    VALUES ($1, NOW(), $2, $3, $4::jsonb, NOW())
                    ON CONFLICT (name) DO UPDATE
                    SET heartbeat_at=NOW(),
                        status=EXCLUDED.status,
                        current_job_id=EXCLUDED.current_job_id,
                        meta_json=EXCLUDED.meta_json,
                        updated_at=NOW()
                    """,
                    self.name,
                    status,
                    current_job_id,
                    json.dumps(meta or {}, ensure_ascii=False),
                )
        except Exception:
            return
