"""Run Sentinel V7 edge heartbeat + store-and-forward synchronization.

Required environment variables:
  SENTINEL_CLOUD_URL       e.g. https://app.sentinel-cold.com
  SENTINEL_DEVICE_ID       e.g. sentinel-pi-001
  SENTINEL_EQUIPMENT_ID    e.g. LCSB00510
Optional:
  SENTINEL_CLOUD_API_KEY
  SENTINEL_EDGE_INTERVAL_SECONDS (default 15)
"""
from __future__ import annotations

import os
import sqlite3
import time
from pathlib import Path

from config.settings import DATABASE_PATH
from sentinel.cloud.edge_client import EdgeCloudClient


def new_measurements(after_id: int, limit: int = 500) -> list[dict[str, object]]:
    connection = sqlite3.connect(DATABASE_PATH)
    connection.row_factory = sqlite3.Row
    try:
        rows = connection.execute(
            "SELECT * FROM measurements WHERE id>? ORDER BY id LIMIT ?", (after_id, limit)
        ).fetchall()
        return [dict(row) for row in rows]
    finally:
        connection.close()


def main() -> None:
    cloud_url = os.environ["SENTINEL_CLOUD_URL"]
    device_id = os.environ["SENTINEL_DEVICE_ID"]
    equipment_id = os.environ["SENTINEL_EQUIPMENT_ID"]
    interval = max(5, int(os.getenv("SENTINEL_EDGE_INTERVAL_SECONDS", "15")))
    outbox = Path(DATABASE_PATH).parent / "sentinel_v7_outbox.db"
    client = EdgeCloudClient(
        cloud_url=cloud_url,
        device_id=device_id,
        equipment_id=equipment_id,
        api_key=os.getenv("SENTINEL_CLOUD_API_KEY", ""),
        outbox_path=outbox,
    )
    print(f"Sentinel V7 edge agent: {device_id} → {cloud_url}")
    while True:
        try:
            client.heartbeat(edge_version="7.0.0", heartbeat_interval_seconds=interval)
            cursor = int(client.get_state("last_enqueued_measurement_id", "0") or 0)
            rows = new_measurements(cursor)
            for row in rows:
                row["source_id"] = str(row["id"])
                client.enqueue(row)
                cursor = max(cursor, int(row["id"]))
            if rows:
                client.set_state("last_enqueued_measurement_id", str(cursor))
            result = client.flush()
            print(f"heartbeat OK · queued/sync accepted={result.get('accepted', 0)} remaining={result.get('remaining', 0)}")
        except Exception as exc:
            # Expected during WAN outages: the outbox remains local and is retried.
            print(f"cloud unavailable · local buffering continues · {exc}")
        time.sleep(interval)


if __name__ == "__main__":
    main()
