import json
import os
import sys
import tempfile

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from src import store


def _fresh_db():
    path = os.path.join(tempfile.mkdtemp(), "t.sqlite")
    conn = store.connect(path)
    store.init_db(conn)
    return conn


def _row(id_, ts, mood, tags, note="", affirmation=""):
    return {"id": id_, "ts": ts, "mood": mood, "tags": json.dumps(tags),
            "note": note, "affirmation": affirmation}


def test_upsert_idempotent():
    conn = _fresh_db()
    rows = [
        _row(1, "2026-07-01T08:00:00+00:00", 4, ["calm"]),
        _row(2, "2026-07-02T08:00:00+00:00", 2, ["sad", "tired"]),
    ]
    store.upsert_entries(conn, rows)
    store.upsert_entries(conn, rows)  # re-run same rows
    count = conn.execute("SELECT COUNT(*) c FROM mood_entries").fetchone()["c"]
    assert count == 2  # no duplication despite double ingest


def test_upsert_updates_on_conflict():
    conn = _fresh_db()
    rows = [_row(1, "2026-07-01T08:00:00+00:00", 4, ["calm"], note="first")]
    store.upsert_entries(conn, rows)
    rows[0]["note"] = "corrected"
    store.upsert_entries(conn, rows)
    got = conn.execute("SELECT note FROM mood_entries WHERE source_id=1").fetchone()["note"]
    assert got == "corrected"


def test_sync_state_high_water_mark():
    conn = _fresh_db()
    store.set_sync_state(conn, "moodtracker_entries", 5)
    store.set_sync_state(conn, "moodtracker_entries", 3)  # older cursor must not regress
    assert store.get_last_synced_id(conn, "moodtracker_entries") == 5
    store.set_sync_state(conn, "moodtracker_entries", 9)
    assert store.get_last_synced_id(conn, "moodtracker_entries") == 9


def test_summary_and_daily_mood():
    conn = _fresh_db()
    rows = [
        _row(1, "2026-07-01T08:00:00+00:00", 4, ["calm"]),
        _row(2, "2026-07-01T20:00:00+00:00", 2, ["tired"]),
        _row(3, "2026-07-02T08:00:00+00:00", 5, ["happy"]),
    ]
    store.upsert_entries(conn, rows)
    s = store.summary(conn)
    assert s["entries"] == 3
    assert s["coverage"]["earliest"] is not None

    daily = store.daily_mood(conn, days=30)
    by_day = {d["day"]: d for d in daily}
    assert by_day["2026-07-01"]["entries"] == 2
    assert by_day["2026-07-01"]["avg_mood"] == 3.0  # (4+2)/2
    assert by_day["2026-07-02"]["avg_mood"] == 5.0


def test_tag_breakdown():
    conn = _fresh_db()
    rows = [
        _row(1, "2026-07-01T08:00:00+00:00", 5, ["happy", "energetic"]),
        _row(2, "2026-07-02T08:00:00+00:00", 1, ["sad", "tired"]),
        _row(3, "2026-07-03T08:00:00+00:00", 2, ["tired"]),
    ]
    store.upsert_entries(conn, rows)
    tags = store.tag_breakdown(conn, days=90, min_count=2)
    by_tag = {t["tag"]: t for t in tags}
    assert by_tag["tired"]["count"] == 2
    assert by_tag["tired"]["avg_mood"] == 1.5
    assert "happy" not in by_tag  # min_count=2 filters singletons


def test_correlate_with_series():
    conn = _fresh_db()
    rows = [
        _row(1, "2026-07-01T08:00:00+00:00", 5, []),
        _row(2, "2026-07-02T08:00:00+00:00", 4, []),
        _row(3, "2026-07-03T08:00:00+00:00", 2, []),
        _row(4, "2026-07-04T08:00:00+00:00", 1, []),
    ]
    store.upsert_entries(conn, rows)
    # perfectly correlated external series (e.g. "hours slept")
    external = {
        "2026-07-01": 8.0, "2026-07-02": 7.0,
        "2026-07-03": 5.0, "2026-07-04": 4.0,
    }
    result = store.correlate_with_series(conn, external, days=30)
    assert result["n"] == 4
    assert result["r"] > 0.99  # near-perfect positive correlation


def test_correlate_too_few_points():
    conn = _fresh_db()
    store.upsert_entries(conn, [_row(1, "2026-07-01T08:00:00+00:00", 3, [])])
    result = store.correlate_with_series(conn, {"2026-07-01": 5.0}, days=30)
    assert result["n"] == 1
    assert result["r"] is None
