"""Tests for `openrun.setup.init_workspace` — idempotency, state reporting."""

from __future__ import annotations

import sqlite3
from pathlib import Path

from openrun.config import Config
from openrun.setup import EXPECTED_TABLES, init_workspace


def _cfg(tmp_path: Path) -> Config:
    """A Config that points at an isolated tmp_path DB."""
    return Config(db_path=tmp_path / "test.db")


def _empty_secrets(tmp_path: Path) -> Path:
    """A non-existent secrets dir under tmp_path — guarantees tests never read the real one."""
    return tmp_path / ".secrets"


def test_first_run_creates_db(tmp_path: Path) -> None:
    cfg = _cfg(tmp_path)
    status = init_workspace(config=cfg, secrets_dir=_empty_secrets(tmp_path))

    assert not status.db_existed_before
    assert cfg.db_path.exists()
    assert status.is_ready()
    assert set(EXPECTED_TABLES).issubset(status.tables_present)


def test_second_run_is_idempotent(tmp_path: Path) -> None:
    cfg = _cfg(tmp_path)
    secrets = _empty_secrets(tmp_path)

    first = init_workspace(config=cfg, secrets_dir=secrets)
    second = init_workspace(config=cfg, secrets_dir=secrets)

    assert not first.db_existed_before
    assert second.db_existed_before
    assert first.tables_present == second.tables_present
    # Idempotent: re-running mutates nothing, so all counts stay zero.
    assert all(n == 0 for n in second.table_counts.values())


def test_preserves_existing_data(tmp_path: Path) -> None:
    cfg = _cfg(tmp_path)
    secrets = _empty_secrets(tmp_path)

    init_workspace(config=cfg, secrets_dir=secrets)

    # Insert one row through a raw connection; init_workspace must not touch it.
    conn = sqlite3.connect(cfg.db_path)
    conn.execute(
        "INSERT INTO activities (activity_id, raw, fetched_at) VALUES (1, '{}', 'now')"
    )
    conn.commit()
    conn.close()

    status = init_workspace(config=cfg, secrets_dir=secrets)
    assert status.db_existed_before
    assert status.table_counts["activities"] == 1


def test_reports_auth_tokens(tmp_path: Path) -> None:
    cfg = _cfg(tmp_path)
    secrets = tmp_path / ".secrets"

    missing = init_workspace(config=cfg, secrets_dir=secrets)
    assert not missing.auth_tokens_present

    secrets.mkdir()
    (secrets / "oauth1_token.json").write_text("{}")

    present = init_workspace(config=cfg, secrets_dir=secrets)
    assert present.auth_tokens_present


def test_reports_sync_state(tmp_path: Path) -> None:
    cfg = _cfg(tmp_path)
    secrets = _empty_secrets(tmp_path)

    init_workspace(config=cfg, secrets_dir=secrets)
    conn = sqlite3.connect(cfg.db_path)
    conn.execute(
        "INSERT INTO sync_state (key, value, updated_at) VALUES (?, ?, datetime('now'))",
        ("last_sync_utc", "2026-05-18T10:30:00"),
    )
    conn.commit()
    conn.close()

    status = init_workspace(config=cfg, secrets_dir=secrets)
    assert status.last_sync_utc == "2026-05-18T10:30:00"
    assert status.last_ingest_utc is None


def test_status_serialises_to_json(tmp_path: Path) -> None:
    """`to_dict()` output must be JSON-encodable for `--json` CLI usage."""
    import json

    status = init_workspace(config=_cfg(tmp_path), secrets_dir=_empty_secrets(tmp_path))
    blob = json.dumps(status.to_dict(), default=str)
    parsed = json.loads(blob)
    assert parsed["db_path"].endswith("test.db")
    assert parsed["db_existed_before"] is False
    assert "activities" in parsed["tables_present"]
