# tiny_node — join Wi-Fi from the provisioned list, heartbeat every 30 s, answer nothing yet.
# Runs on the board only (network/urequests); the host tests import tiny_config/tiny_provision alone.
import json
import time

import tiny_config

CAPABILITIES = {{capabilities}}
HEARTBEAT_S = 30


def join_wifi(cfg, timeout_s=20):
    import network
    sta = network.WLAN(network.STA_IF)
    sta.active(True)
    for n in tiny_config.networks(cfg):
        sta.connect(n["ssid"], n.get("key", ""))
        t0 = time.time()
        while not sta.isconnected() and time.time() - t0 < timeout_s:
            time.sleep(0.5)
        if sta.isconnected():
            return sta.ifconfig()[0]
    return None


def heartbeat(cfg, ip=None):
    import urequests
    body = {"deviceId": cfg["device_id"], "token": cfg["token"], "capabilities": CAPABILITIES}
    if ip:
        body["lanUrl"] = "http://%s:8080" % ip
    r = urequests.post(cfg.get("api", tiny_config.DEFAULT_API) + "/api/devices/heartbeat",
                       data=json.dumps(body), headers={"Content-Type": "application/json"})
    ok = r.status_code == 200
    r.close()
    return ok, r.status_code


def run():
    cfg = tiny_config.load_raw() or {}
    if not tiny_config.complete(cfg):
        print("{{slug}}: not provisioned — run: npx tiny-tech flash --body {{slug}} --from ./firmware --wifi ssid:key")
        return
    ip = join_wifi(cfg)
    print("{{slug}}: wifi", ip)
    while True:
        try:
            ok, code = heartbeat(cfg, ip)
            if code == 401:
                print("{{slug}}: token revoked — re-provision")
                return
        except Exception as e:  # noqa: BLE001 — a network blip is not a reason to stop
            print("{{slug}}: heartbeat error", e)
        time.sleep(HEARTBEAT_S)
