import json
import os
import sqlite3
import sys
import tempfile

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

from src import store
from src.sync import run_sync


def _mock_moodtracker_db(entries):
    """Build a SQLite file with moodtracker's exact `entries` schema
    (see /home/alvis/moodtracker/app.py init_db) and seed rows."""
    path = os.path.join(tempfile.mkdtemp(), "mood.db")
    conn = sqlite3.connect(path)
    conn.execute("""
        CREATE TABLE entries (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            ts TEXT NOT NULL,
            mood INTEGER NOT NULL,
            tags TEXT NOT NULL,
            note TEXT,
            affirmation TEXT
        )
    """)
    for ts, mood, tags, note, aff in entries:
        conn.execute(
            "INSERT INTO entries (ts, mood, tags, note, affirmation) VALUES (?,?,?,?,?)",
            (ts, mood, json.dumps(tags), note, aff),
        )
    conn.commit()
    conn.close()
    return path


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


def test_sync_pulls_all_rows_first_run():
    source = _mock_moodtracker_db([
        ("2026-07-01T08:00:00+00:00", 4, ["calm"], "n1", "a1"),
        ("2026-07-02T08:00:00+00:00", 2, ["sad", "tired"], "n2", ""),
    ])
    conn = _archive_conn()
    totals = run_sync(conn, source_db_path=source)
    assert totals["errors"] == []
    assert totals["entries"] == 2
    assert conn.execute("SELECT COUNT(*) c FROM mood_entries").fetchone()["c"] == 2


def test_sync_is_idempotent_across_runs():
    source = _mock_moodtracker_db([
        ("2026-07-01T08:00:00+00:00", 4, ["calm"], "", ""),
    ])
    conn = _archive_conn()
    run_sync(conn, source_db_path=source)
    run_sync(conn, source_db_path=source)  # nothing new, cursor unchanged
    run_sync(conn, source_db_path=source)
    assert conn.execute("SELECT COUNT(*) c FROM mood_entries").fetchone()["c"] == 1


def test_sync_picks_up_new_rows_incrementally():
    path = _mock_moodtracker_db([
        ("2026-07-01T08:00:00+00:00", 4, ["calm"], "", ""),
    ])
    conn = _archive_conn()
    run_sync(conn, source_db_path=path)
    assert conn.execute("SELECT COUNT(*) c FROM mood_entries").fetchone()["c"] == 1

    # a new entry gets logged upstream between syncs
    src_conn = sqlite3.connect(path)
    src_conn.execute(
        "INSERT INTO entries (ts, mood, tags, note, affirmation) VALUES (?,?,?,?,?)",
        ("2026-07-03T09:00:00+00:00", 5, json.dumps(["happy"]), "", ""),
    )
    src_conn.commit()
    src_conn.close()

    run_sync(conn, source_db_path=path)
    assert conn.execute("SELECT COUNT(*) c FROM mood_entries").fetchone()["c"] == 2


def test_sync_records_error_when_source_missing():
    conn = _archive_conn()
    totals = run_sync(conn, source_db_path="/nonexistent/path/mood.db")
    assert totals["errors"]
    row = conn.execute(
        "SELECT last_status, last_error FROM sync_state WHERE stream_key='moodtracker_entries'"
    ).fetchone()
    assert row["last_status"] == "error"
    assert row["last_error"]


def test_sync_never_writes_to_source_db():
    """The source connection is opened read-only; a failed write attempt
    would raise, and run_sync should never attempt one in the first place."""
    source = _mock_moodtracker_db([("2026-07-01T08:00:00+00:00", 3, [], "", "")])
    before = os.path.getmtime(source)
    conn = _archive_conn()
    run_sync(conn, source_db_path=source)
    after = os.path.getmtime(source)
    assert before == after
