"""Entry point for heartbeat monitoring."""

from __future__ import annotations

import logging
import os
import sys
import time
from pathlib import Path

from heartbeat.alert_dedup import get_redis, should_alert
from heartbeat.checks import run_checks
from heartbeat.config import ALERT_DEDUP_TTL, HEALTH_GATE_KEYS
from heartbeat.formatter import format_message
from heartbeat.state import load_pending, save_pending
from heartbeat.telegram import delete_expired, push_deadman_switch, send_telegram

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger("health-heartbeat")


def main() -> int:
    token = os.environ.get("OPENDEVIATIONBAR_TELEGRAM_TOKEN", "")
    chat_id = os.environ.get("OPENDEVIATIONBAR_TELEGRAM_CHAT_ID", "90417581")

    if not token:
        logger.error("Telegram not configured — set OPENDEVIATIONBAR_TELEGRAM_TOKEN")
        return 1

    try:
        return _main(token, chat_id)
    except Exception:
        host = os.environ.get("HOSTNAME") or os.uname().nodename
        logger.critical(
            "Unhandled exception in heartbeat — sending emergency alert", exc_info=True
        )
        try:
            import html as _html
            import traceback as _tb

            tb_text = _html.escape(_tb.format_exc()[-1000:])
            send_telegram(
                token,
                chat_id,
                f"🚨 <b>HEARTBEAT CRASHED</b> on {_html.escape(host)}\n\n"
                f"Unhandled exception in health_heartbeat.py — monitoring is down. "
                f"Check journalctl immediately.\n\n<pre>{tb_text}</pre>",
                silent=False,
            )
        except Exception:
            logger.critical("Emergency Telegram alert also failed", exc_info=True)
        return 2


def _main(token: str, chat_id: str) -> int:
    # Step 1: Delete expired healthy messages
    deleted = delete_expired()
    if deleted:
        logger.info("Cleaned up %d expired heartbeat messages", deleted)

    # Step 2: Run health checks
    results = run_checks()
    healthy = all(
        results.get(k) is not False
        for k in HEALTH_GATE_KEYS
    )

    # Step 3: Alert dedup via Redis (Issue #186)
    failed_checks = sorted(k for k, v in results.items() if v is False)
    alert_fingerprint = "|".join(failed_checks) if failed_checks else ""

    redis_client = get_redis() if not healthy else None
    should_send_alert = healthy or should_alert(redis_client, alert_fingerprint)

    if not should_send_alert:
        logger.info(
            "Alert suppressed (duplicate within %ds): %s",
            ALERT_DEDUP_TTL,
            alert_fingerprint,
        )
        message = format_message(results, healthy)
        msg_id = send_telegram(token, chat_id, message, silent=True)
        if msg_id:
            records = load_pending()
            records.append({"message_id": msg_id, "sent_at": time.time()})
            save_pending(records)
        return 0

    # Step 4: Send message
    auto_healed = bool(results.get("auto_healed_pth"))
    message = format_message(results, healthy)
    msg_id = send_telegram(token, chat_id, message, silent=healthy and not auto_healed)

    if not msg_id:
        logger.error("Failed to send heartbeat message")
        return 1

    # Step 5: Track healthy messages for future deletion
    if healthy:
        records = load_pending()
        records.append({"message_id": msg_id, "sent_at": time.time()})
        save_pending(records)
        logger.info(
            "Heartbeat OK (message_id=%d, %d pending for cleanup)",
            msg_id,
            len(records),
        )
    else:
        logger.warning("UNHEALTHY heartbeat sent (persistent, will not auto-delete)")
        for check, value in results.items():
            if value is False:
                logger.warning("  FAILED: %s", check)

    # Step 6: ntfy dead-man's-switch (Issue #193)
    push_deadman_switch()

    # Step 7: Cleanup old artifacts (keep last 7 days, preserve symlinks)
    artifacts_dir = Path.home() / "opendeviationbar-py" / "artifacts"
    if artifacts_dir.exists():
        cutoff = time.time() - 7 * 86400
        for f in artifacts_dir.glob("*.json"):
            if f.is_symlink():
                continue
            try:
                if f.stat().st_mtime < cutoff:
                    f.unlink(missing_ok=True)
            except OSError:
                logger.debug("failed to clean artifact %s", f, exc_info=True)

    return 0


if __name__ == "__main__":
    sys.exit(main())
