#!/usr/bin/env python3
"""
Kitzu — Blood Biomarker Collector

Parses blood test data from dashboard-data.json (InsideTracker format)
and stores normalized records in the Kitzu data lake.

This collector reads from the existing dashboard data rather than
scraping InsideTracker directly. When new blood tests come in,
they get added to dashboard-data.json first (via Chrome MCP or manual),
then this collector normalizes and stores them.

Usage:
    python3 collect_blood.py                # Import latest from dashboard-data.json
    python3 collect_blood.py --status       # Show blood data in data lake

Writes to: kitzu/data/blood/{date}_{source}.json
Updates:   kitzu/data/unified/profile.json (blood section)
"""

import sys
import json
import logging
import argparse
from datetime import datetime
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from schema import (
    BloodMarker, BloodTest, store_blood_test, load_blood_history,
    load_profile, save_profile, BLOOD_DIR, data_lake_status
)

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    datefmt="%H:%M:%S",
)
log = logging.getLogger("kitzu.blood")

# ── Source data ──────────────────────────────────────────────

DASHBOARD_PATH = Path(__file__).resolve().parent.parent.parent / "dashboard-data.json"


def parse_trend(trend_str: str) -> list:
    """Parse trend string like '755→689→675→570→651' into list of floats."""
    if not trend_str:
        return []
    # Handle various arrow characters
    parts = trend_str.replace("→", "|").replace("↑", "|").replace("↓", "|").split("|")
    values = []
    for p in parts:
        p = p.strip()
        try:
            values.append(float(p))
        except ValueError:
            continue
    return values


def status_from_category(category: str) -> str:
    """Map dashboard category to normalized status."""
    return {
        "critical": "critical",
        "watch": "at_risk",
        "good": "optimal",
    }.get(category, "unknown")


def import_from_dashboard() -> BloodTest:
    """Parse bloodwork from dashboard-data.json into a BloodTest."""
    if not DASHBOARD_PATH.exists():
        log.error(f"Dashboard data not found at {DASHBOARD_PATH}")
        return None

    data = json.loads(DASHBOARD_PATH.read_text())
    bw = data.get("bloodwork", {})

    if not bw:
        log.error("No bloodwork section in dashboard-data.json")
        return None

    test_date = bw.get("testDate", "unknown")
    source = bw.get("source", "InsideTracker")
    flags = bw.get("flags", {})

    markers = []

    # Process each category: critical, watch, good
    for category, items in flags.items():
        for item in items:
            marker = BloodMarker(
                name=item["marker"],
                value=float(item["value"]),
                unit=item.get("unit", ""),
                optimal_range=item.get("range", ""),
                status=status_from_category(category),
                date=test_date,
                source=source,
                trend=parse_trend(item.get("trend", "")),
                action=item.get("action") or item.get("note"),
            )
            markers.append(marker)

    # Inner Age
    inner_age_data = bw.get("innerAge", {})
    inner_age = inner_age_data.get("current")

    test = BloodTest(
        date=test_date,
        source=source,
        markers=markers,
        inner_age=inner_age,
        marker_count=len(markers),
    )

    log.info(f"Parsed {len(markers)} markers from {source} ({test_date})")
    log.info(f"  Critical: {sum(1 for m in markers if m.status == 'critical')}")
    log.info(f"  At risk:  {sum(1 for m in markers if m.status == 'at_risk')}")
    log.info(f"  Optimal:  {sum(1 for m in markers if m.status == 'optimal')}")
    if inner_age:
        log.info(f"  InnerAge: {inner_age}")

    return test


def update_profile_blood(test: BloodTest):
    """Update the unified profile with latest blood data."""
    profile = load_profile()

    profile["blood"]["last_sync"] = datetime.now().isoformat()
    profile["blood"]["latest_test"] = test.date
    profile["blood"]["inner_age"] = test.inner_age

    # Update markers dict (latest value for each marker)
    for m in test.markers:
        profile["blood"]["markers"][m.name] = {
            "value": m.value,
            "unit": m.unit,
            "range": m.optimal_range,
            "status": m.status,
            "trend": m.trend,
            "date": m.date,
            "action": m.action,
        }

    # Add to test history (avoid duplicates)
    history_entry = {
        "date": test.date,
        "source": test.source,
        "marker_count": test.marker_count,
        "inner_age": test.inner_age,
    }
    existing_dates = [h["date"] for h in profile["blood"]["test_history"]]
    if test.date not in existing_dates:
        profile["blood"]["test_history"].append(history_entry)
        profile["blood"]["test_history"].sort(key=lambda h: h["date"])

    # Import InnerAge history from dashboard
    dashboard = json.loads(DASHBOARD_PATH.read_text())
    ia_history = dashboard.get("bloodwork", {}).get("innerAge", {}).get("history", [])
    if ia_history:
        for entry in ia_history:
            hist_entry = {
                "date": entry["date"],
                "source": "InsideTracker",
                "marker_count": 0,  # Unknown for historical
                "inner_age": entry.get("innerAge"),
            }
            if entry["date"] not in existing_dates:
                profile["blood"]["test_history"].append(hist_entry)
        profile["blood"]["test_history"].sort(key=lambda h: h["date"])

    save_profile(profile)
    log.info("Unified profile updated (blood section)")


# ── Vitals Import ────────────────────────────────────────────

def import_vitals():
    """Import blood pressure and weight from dashboard-data.json into profile."""
    if not DASHBOARD_PATH.exists():
        return

    data = json.loads(DASHBOARD_PATH.read_text())
    profile = load_profile()

    # Blood pressure
    bp = data.get("bloodPressure", {})
    if bp:
        profile["vitals"]["blood_pressure"] = {
            "systolic": bp.get("systolic"),
            "diastolic": bp.get("diastolic"),
            "pulse": bp.get("pulse"),
            "date": bp.get("date"),
            "source": bp.get("source", "iHealth"),
        }
        # History
        bp_hist = bp.get("history", [])
        if bp_hist:
            profile["vitals"]["bp_history"] = bp_hist

    # Weight + body composition
    weight = data.get("weight", {})
    if weight:
        profile["vitals"]["weight"] = {
            "value_lb": weight.get("current"),
            "body_fat_pct": weight.get("bodyFat"),
            "muscle_mass": weight.get("muscleMass"),
            "lean_mass": weight.get("leanMass"),
            "bone_mass": weight.get("boneMass"),
            "body_water": weight.get("bodyWater"),
            "visceral_fat": weight.get("visceralFat"),
            "bmr": weight.get("bmr"),
            "bmi": weight.get("bmi"),
            "date": weight.get("lastWeighIn") or weight.get("date"),
            "source": weight.get("source", "Health Connect"),
        }
        # Weight series as history
        series = weight.get("series30d", [])
        if series:
            profile["vitals"]["weight_history"] = series

    # Microbiome (Viome food recs)
    viome_path = Path(__file__).resolve().parent.parent.parent / "data" / "health" / "foods_viome.json"
    if viome_path.exists():
        try:
            viome = json.loads(viome_path.read_text())
            profile["microbiome"]["source"] = "Viome"
            profile["microbiome"]["food_recs"] = viome
            profile["microbiome"]["last_sync"] = datetime.now().isoformat()
            log.info(f"Viome food recs imported")
        except Exception as e:
            log.warning(f"Failed to import Viome data: {e}")

    profile["vitals"]["last_sync"] = datetime.now().isoformat()
    save_profile(profile)
    log.info("Unified profile updated (vitals + microbiome sections)")


# ── Main ─────────────────────────────────────────────────────

def main():
    parser = argparse.ArgumentParser(description="Kitzu Blood Biomarker Collector")
    parser.add_argument("--status", action="store_true", help="Show blood data in data lake")
    parser.add_argument("--vitals", action="store_true", help="Also import vitals (BP, weight, Viome)")
    args = parser.parse_args()

    if args.status:
        history = load_blood_history()
        print(f"\nBlood tests in data lake: {len(history)}")
        for t in history:
            print(f"  {t['date']} | {t['source']} | {t['marker_count']} markers | InnerAge: {t.get('inner_age', '?')}")
        return

    # Import bloodwork
    test = import_from_dashboard()
    if test:
        store_blood_test(test)
        update_profile_blood(test)

        print(f"\nImported {test.marker_count} markers from {test.source} ({test.date})")
        if test.inner_age:
            print(f"InnerAge: {test.inner_age}")

        # Show critical markers
        critical = [m for m in test.markers if m.status == "critical"]
        if critical:
            print(f"\nCritical markers ({len(critical)}):")
            for m in critical:
                print(f"  {m.name}: {m.value} {m.unit} (range: {m.optimal_range})")

    # Import vitals too (always, since it's available)
    import_vitals()
    print("Vitals imported (BP, weight, body composition, Viome)")


if __name__ == "__main__":
    main()
