"""Web service health heartbeat."""

from __future__ import annotations

import logging
import os
import threading
import time
from typing import TYPE_CHECKING

from .redis_io import (
    KEY_CONTROL_LATEST,
    KEY_HEALTH_CONTROL,
    KEY_HEALTH_TEMPS,
    KEY_TEMPS_LATEST,
    WebRedis,
    payload_age_s,
)

if TYPE_CHECKING:
    from .config import WebConfig

logger = logging.getLogger("hot_tub.web")


def compute_health(redis_io: WebRedis, cfg: WebConfig) -> tuple[str, str]:
    client_ok = redis_io._ensure() is not None  # noqa: SLF001
    if not client_ok:
        return "error", "redis down"

    control = redis_io.get_json(KEY_CONTROL_LATEST)
    temps = redis_io.get_json(KEY_TEMPS_LATEST)
    stale = cfg.stale_s
    control_age = payload_age_s(control)
    temps_age = payload_age_s(temps)
    if control_age is not None and control_age > stale:
        return "degraded", "control:latest stale"
    if temps_age is not None and temps_age > stale:
        return "degraded", "temps:latest stale"
    if control is None or temps is None:
        return "degraded", "missing upstream snapshots"
    return "ok", "serving; redis ok"


def health_snapshot(redis_io: WebRedis, cfg: WebConfig) -> dict:
    status, detail = compute_health(redis_io, cfg)
    from datetime import datetime, timezone

    ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
    return {
        "service": "web",
        "ts": ts,
        "status": status,
        "detail": detail,
        "pid": os.getpid(),
    }


def start_health_thread(redis_io: WebRedis, cfg: WebConfig, stop: threading.Event) -> threading.Thread:
    def _loop() -> None:
        while not stop.is_set():
            payload = health_snapshot(redis_io, cfg)
            redis_io.publish_health(payload)
            stop.wait(cfg.heartbeat_s)

    thread = threading.Thread(target=_loop, daemon=True)
    thread.start()
    return thread


def api_health_payload(redis_io: WebRedis, cfg: WebConfig) -> dict:
    web = health_snapshot(redis_io, cfg)
    return {
        "web": web,
        "control_age_s": payload_age_s(redis_io.get_json(KEY_CONTROL_LATEST)),
        "temps_age_s": payload_age_s(redis_io.get_json(KEY_TEMPS_LATEST)),
        "health_control": redis_io.get_json(KEY_HEALTH_CONTROL),
        "health_temps": redis_io.get_json(KEY_HEALTH_TEMPS),
    }
