#!/usr/bin/env python3
# oura-health-report.py
# Pulls Oura data and posts a daily health report to Discord #health channel
# Called by cron every morning

import json
import urllib.request
import urllib.error
import os
import sys
from datetime import date, timedelta

# --- Config ---
OURA_TOKEN_FILE = os.path.expanduser("~/.openclaw/secrets/oura-api-key.txt")
DISCORD_TOKEN_FILE = os.path.expanduser("~/.openclaw/secrets/discord-bot-token.txt")
HEALTH_CHANNEL_ID = "1481326526472654971"  # #health in ZHQ

def read_secret(path):
    with open(path) as f:
        return f.read().strip()

def oura_get(endpoint, start_date, end_date):
    token = read_secret(OURA_TOKEN_FILE)
    url = f"https://api.ouraring.com/v2/usercollection/{endpoint}?start_date={start_date}&end_date={end_date}"
    req = urllib.request.Request(url, headers={"Authorization": f"Bearer {token}"})
    with urllib.request.urlopen(req) as r:
        return json.loads(r.read())

def discord_post(channel_id, message):
    import subprocess, re
    token = re.sub(r'\s+', '', open(DISCORD_TOKEN_FILE).read())
    url = f"https://discord.com/api/v10/channels/{channel_id}/messages"
    result = subprocess.run([
        "curl", "-s", "-X", "POST", url,
        "-H", f"Authorization: Bot {token}",
        "-H", "Content-Type: application/json",
        "-d", json.dumps({"content": message})
    ], capture_output=True, text=True)
    return json.loads(result.stdout)

def score_emoji(score):
    if score >= 85: return "🟢"
    if score >= 70: return "🟡"
    if score >= 50: return "🟠"
    return "🔴"

def seconds_to_hm(s):
    if not s: return "—"
    h = s // 3600
    m = (s % 3600) // 60
    return f"{h}h {m}m"

def nap_recommendation(sleep_score, readiness_score):
    avg = (sleep_score + readiness_score) / 2
    if avg < 60:
        return "😴 **Take a nap.** Your body needs recovery — 20-30 min would help."
    elif avg < 75:
        return "🛋️ **Optional nap.** You're okay but a short rest wouldn't hurt."
    else:
        return "✅ **No nap needed.** You're well recovered — go crush it."

def main():
    today = date.today().isoformat()
    yesterday = (date.today() - timedelta(days=1)).isoformat()

    try:
        sleep_data = oura_get("daily_sleep", yesterday, today).get("data", [])
        readiness_data = oura_get("daily_readiness", yesterday, today).get("data", [])
        sleep_detail = oura_get("sleep", yesterday, today).get("data", [])

        if not sleep_data or not readiness_data:
            discord_post(HEALTH_CHANNEL_ID, "⚠️ No Oura data available for today yet.")
            return

        sleep = sleep_data[-1]
        readiness = readiness_data[-1]
        detail = sleep_detail[-1] if sleep_detail else {}

        ss = sleep.get("score", 0)
        rs = readiness.get("score", 0)
        sc = sleep.get("contributors", {})
        rc = readiness.get("contributors", {})

        total = detail.get("total_sleep_duration", 0)
        deep = detail.get("deep_sleep_duration", 0)
        rem = detail.get("rem_sleep_duration", 0)
        efficiency = detail.get("efficiency", 0)
        hrv = detail.get("average_hrv", 0)
        rhr = detail.get("lowest_heart_rate", 0)

        nap = nap_recommendation(ss, rs)

        msg = f"""🌅 **Good morning, Mike — Health Report for {today}**

**Sleep** {score_emoji(ss)} {ss}/100
• Total: {seconds_to_hm(total)} | Deep: {seconds_to_hm(deep)} | REM: {seconds_to_hm(rem)}
• Efficiency: {efficiency}% | HRV: {hrv} | Resting HR: {rhr} bpm

**Readiness** {score_emoji(rs)} {rs}/100
• HRV Balance: {rc.get('hrv_balance', '—')} | Body Temp: {rc.get('body_temperature', '—')}
• Sleep Balance: {rc.get('sleep_balance', '—')} | Activity Balance: {rc.get('activity_balance', '—')}

{nap}

_Ask me anything about your health data or what to do today._"""

        discord_post(HEALTH_CHANNEL_ID, msg)
        print(f"✅ Health report posted for {today}")

    except Exception as e:
        error_msg = f"⚠️ Health report failed: {str(e)}"
        print(error_msg, file=sys.stderr)
        try:
            discord_post(HEALTH_CHANNEL_ID, error_msg)
        except:
            pass

if __name__ == "__main__":
    main()
