import os
import sqlite3

import server


def rec(**kwargs):
    base = {"subject": "chicho", "local_date": "2026-05-19"}
    base.update(kwargs)
    base.setdefault("fingerprint", server.canonical_fingerprint(base))
    return base


def test_classifies_hevy_vs_google_fit_exercise():
    hevy = rec(type="exercise", source="com.hevy", exercise_type="70", title="Min-Max", minutes=117, start="a", end="b")
    fit = rec(type="exercise", source="com.google.android.apps.fitness", exercise_type="79", minutes=41, start="c", end="d")
    assert server.classify_record(hevy)["class"] == "explicit_workout"
    assert server.classify_record(fit)["class"] == "auto_activity"


def test_summary_splits_workout_and_auto_activity_minutes():
    records = [
        rec(type="daily_aggregate", source="health_connect", steps=11540, distance_m=11122, active_kcal=0, total_kcal=1544),
        rec(type="exercise", source="com.hevy", exercise_type="70", title="Min-Max", minutes=117, start="2026-05-19T18:23:32Z", end="2026-05-19T20:20:51Z"),
        rec(type="exercise", source="com.google.android.apps.fitness", exercise_type="79", minutes=41, start="2026-05-19T15:24:07Z", end="2026-05-19T16:06:00Z"),
    ]
    summary, provenance = server.compute_daily_summary(records)
    assert summary["steps"] == 11540
    assert summary["workout_minutes"] == 117
    assert summary["auto_activity_minutes"] == 41
    assert summary["exercise_minutes"] == 158
    assert summary["workout_count"] == 1
    assert summary["auto_activity_count"] == 1
    assert "workout_minutes" in provenance["by_metric"]
    assert "auto_activity_minutes" in provenance["by_metric"]


def test_dedup_prefers_named_source_over_legacy_health_connect():
    legacy = rec(type="exercise", source="health_connect", exercise_type="79", minutes=20, start="2026-05-19T12:00:00Z", end="2026-05-19T12:20:00Z")
    google = rec(type="exercise", source="com.google.android.apps.fitness", exercise_type="79", minutes=20, start="2026-05-19T12:00:00Z", end="2026-05-19T12:20:00Z")
    # Force same semantic fingerprint even with different source.
    fp = server.canonical_fingerprint(google)
    legacy["fingerprint"] = fp
    google["fingerprint"] = fp
    summary, provenance = server.compute_daily_summary([legacy, google])
    assert summary["auto_activity_minutes"] == 20
    assert len(provenance["ignored"]) == 1
    assert provenance["ignored"][0]["source"] == "health_connect"


def test_nutrition_intake_does_not_mix_with_burned_calories():
    records = [
        rec(type="daily_aggregate", source="health_connect", total_kcal=1905, active_kcal=0, steps=1000),
        rec(type="nutrition", source="com.myfitnesspal.android", energy_kcal=600, protein_g=45, carbs_g=70, fat_g=20, start="2026-05-19T13:00:00Z", end="2026-05-19T13:10:00Z"),
    ]
    summary, _ = server.compute_daily_summary(records)
    assert summary["calories"] == 1905
    assert summary["total_kcal"] == 1905
    assert summary["nutrition_kcal"] == 600
    assert summary["protein_g"] == 45


def test_legacy_wide_aggregate_is_ignored():
    records = [
        rec(type="aggregated", source="health_connect", steps=95229, total_kcal=13332, period_start="2026-05-11T22:44:38Z", period_end="2026-05-18T22:44:38Z"),
        rec(type="exercise", source="health_connect", exercise_type="79", minutes=27, start="2026-05-11T23:34:38Z", end="2026-05-12T00:02:12Z"),
    ]
    summary, provenance = server.compute_daily_summary(records)
    assert summary["steps"] == 0
    assert summary["total_kcal"] == 0
    assert summary["auto_activity_minutes"] == 27
    assert provenance["ignored"][0]["reason"] == "stale_wide_aggregate"


def test_rebuild_summary_writes_new_columns(tmp_path, monkeypatch):
    db = sqlite3.connect(tmp_path / "health.db")
    db.execute("PRAGMA journal_mode=WAL")
    monkeypatch.setattr(server, "DB_PATH", str(tmp_path / "health.db"))
    db.close()
    db = server.init_db()
    records = [
        rec(type="daily_aggregate", source="health_connect", steps=10, distance_m=20),
        rec(type="exercise", source="com.hevy", exercise_type="70", title="Lift", minutes=30, start="2026-05-19T10:00:00Z", end="2026-05-19T10:30:00Z"),
    ]
    for r in records:
        n = server._normalize_record(r, server.DEFAULT_TIMEZONE, "chicho")
        db.execute(
            "INSERT INTO raw_data (subject, data_type, record_key, local_date, source, data_json) VALUES (?, ?, ?, ?, ?, ?)",
            (n["subject"], n["data_type"], n["record_key"], n["local_date"], n["source"], __import__('json').dumps(n["record"])),
        )
    db.commit()
    server._rebuild_daily_summary(db, "chicho", "2026-05-19")
    row = db.execute("SELECT steps, workout_minutes, auto_activity_minutes, exercise_minutes, workout_count FROM daily_summary WHERE subject='chicho' AND date='2026-05-19'").fetchone()
    assert row == (10, 30, 0, 30, 1)


def test_summary_dict_uses_explicit_column_order_for_migrated_schema(tmp_path, monkeypatch):
    monkeypatch.setattr(server, "DB_PATH", str(tmp_path / "health.db"))
    db = server.init_db()
    db.execute(
        "INSERT INTO daily_summary (subject, date, steps, total_kcal, workout_minutes, auto_activity_minutes, exercise_minutes, workout_count, auto_activity_count) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
        ("chicho", "2026-05-19", 10, 1000.0, 30, 40, 70, 1, 2),
    )
    row = db.execute(f"SELECT {', '.join(server.SUMMARY_COLUMNS)} FROM daily_summary WHERE subject='chicho'").fetchone()
    d = server._summary_dict(row)
    assert d["steps"] == 10
    assert d["total_kcal"] == 1000.0
    assert d["workout_minutes"] == 30
    assert d["auto_activity_minutes"] == 40
