#!/usr/bin/env python3
# oura.py - Oura Ring data query tool for Harvey
#
# Usage:
#   python3 tools/oura.py sleep [days]
#   python3 tools/oura.py readiness [days]
#   python3 tools/oura.py activity [days]
#   python3 tools/oura.py hrv [days]
#   python3 tools/oura.py summary [days]   (default: all data for today)

import sys
import json
import os
import re
import subprocess
from datetime import date, timedelta

TOKEN_FILE = os.path.expanduser("~/.openclaw/secrets/oura-api-key.txt")

def get_token():
    return re.sub(r'\s+', '', open(TOKEN_FILE).read())

def oura_get(endpoint, start_date, end_date):
    token = get_token()
    url = f"https://api.ouraring.com/v2/usercollection/{endpoint}?start_date={start_date}&end_date={end_date}"
    result = subprocess.run(
        ["curl", "-s", url, "-H", f"Authorization: Bearer {token}"],
        capture_output=True, text=True
    )
    return json.loads(result.stdout)

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

def score_label(score):
    if score is None: return "N/A"
    if score >= 85: return f"{score} (Optimal)"
    if score >= 70: return f"{score} (Good)"
    if score >= 50: return f"{score} (Fair)"
    return f"{score} (Poor)"

def get_dates(days=1):
    end = date.today()
    start = end - timedelta(days=days)
    return start.isoformat(), end.isoformat()

def cmd_sleep(days=1):
    start, end = get_dates(days)
    daily = oura_get("daily_sleep", start, end).get("data", [])
    detail = oura_get("sleep", start, end).get("data", [])

    if not daily:
        print("No sleep data available.")
        return

    for i, d in enumerate(reversed(daily)):
        day = d.get("day")
        score = d.get("score")
        c = d.get("contributors", {})
        det = detail[-(i+1)] if i < len(detail) else {}

        print(f"\n📅 {day} — Sleep Score: {score_label(score)}")
        print(f"  Total: {seconds_to_hm(det.get('total_sleep_duration'))}")
        print(f"  Deep:  {seconds_to_hm(det.get('deep_sleep_duration'))}  |  REM: {seconds_to_hm(det.get('rem_sleep_duration'))}")
        print(f"  Efficiency: {det.get('efficiency', '—')}%")
        print(f"  HRV avg: {det.get('average_hrv', '—')}  |  Resting HR: {det.get('lowest_heart_rate', '—')} bpm")
        print(f"  Bedtime: {str(det.get('bedtime_start',''))[:16]}  →  Wake: {str(det.get('bedtime_end',''))[:16]}")
        print(f"  Contributors: deep={c.get('deep_sleep')} rem={c.get('rem_sleep')} efficiency={c.get('efficiency')} restfulness={c.get('restfulness')}")

def cmd_readiness(days=1):
    start, end = get_dates(days)
    data = oura_get("daily_readiness", start, end).get("data", [])

    if not data:
        print("No readiness data available.")
        return

    for d in reversed(data):
        day = d.get("day")
        score = d.get("score")
        c = d.get("contributors", {})
        temp = d.get("temperature_deviation", 0)

        print(f"\n📅 {day} — Readiness Score: {score_label(score)}")
        print(f"  HRV Balance: {c.get('hrv_balance','—')}  |  Resting HR: {c.get('resting_heart_rate','—')}")
        print(f"  Body Temp deviation: {temp:+.2f}°C")
        print(f"  Sleep Balance: {c.get('sleep_balance','—')}  |  Sleep Regularity: {c.get('sleep_regularity','—')}")
        print(f"  Activity Balance: {c.get('activity_balance','—')}  |  Recovery Index: {c.get('recovery_index','—')}")

def cmd_activity(days=1):
    start, end = get_dates(days)
    data = oura_get("daily_activity", start, end).get("data", [])

    if not data:
        print("No activity data available.")
        return

    for d in reversed(data):
        day = d.get("day")
        score = d.get("score")
        steps = d.get("steps", 0)
        active_cal = d.get("active_calories", 0)
        total_cal = d.get("total_calories", 0)
        met_min = d.get("high_activity_met_minutes", 0)
        sedentary = d.get("sedentary_time", 0)

        print(f"\n📅 {day} — Activity Score: {score_label(score)}")
        print(f"  Steps: {steps:,}")
        print(f"  Active calories: {active_cal}  |  Total calories: {total_cal}")
        print(f"  High activity: {seconds_to_hm(met_min * 60) if met_min else '—'}")
        print(f"  Sedentary time: {seconds_to_hm(sedentary)}")

def cmd_hrv(days=7):
    start, end = get_dates(days)
    data = oura_get("sleep", start, end).get("data", [])

    if not data:
        print("No HRV data available.")
        return

    print(f"\nHRV trend (last {days} days):")
    for d in data:
        day = str(d.get("day", d.get("bedtime_start", "")))[:10]
        hrv = d.get("average_hrv")
        rhr = d.get("lowest_heart_rate")
        if hrv:
            bar = "█" * int(hrv / 5)
            print(f"  {day}  HRV: {hrv:5.1f} {bar}  |  RHR: {rhr}")

def cmd_summary(days=1):
    print("=== OURA HEALTH SUMMARY ===\n")
    cmd_readiness(days)
    cmd_sleep(days)
    cmd_activity(days)

def main():
    args = sys.argv[1:]
    cmd = args[0] if args else "summary"
    days = int(args[1]) if len(args) > 1 else 1

    if cmd == "sleep":
        cmd_sleep(days)
    elif cmd == "readiness":
        cmd_readiness(days)
    elif cmd == "activity":
        cmd_activity(days)
    elif cmd == "hrv":
        cmd_hrv(days if days > 1 else 7)
    elif cmd == "summary":
        cmd_summary(days)
    else:
        print(f"Unknown command: {cmd}")
        print("Usage: oura.py [sleep|readiness|activity|hrv|summary] [days]")

if __name__ == "__main__":
    main()
