# retoor <retoor@molodetz.nl>

import pytest

from devplacepy.database import get_table, purge
from devplacepy.services.dbapi import crud
from devplacepy.services.dbapi.crud import DbApiError

ACTOR = "unit_dbapi_actor"
MARK = "_unit_dbapi_crud"


@pytest.fixture
def clean_bookmarks(local_db):
    yield
    purge("bookmarks", user_uid=MARK)


def _insert():
    return crud.insert_row(
        "bookmarks",
        {"user_uid": MARK, "target_type": "post", "target_uid": "t1"},
        ACTOR,
    )


def test_insert_is_born_live(clean_bookmarks):
    row = _insert()
    assert row["uid"]
    assert row["deleted_at"] is None
    assert row["deleted_by"] is None
    assert row.get("created_at")


def test_insert_rejects_unknown_columns(clean_bookmarks):
    with pytest.raises(DbApiError):
        crud.insert_row("bookmarks", {"user_uid": MARK, "no_such_col": 1}, ACTOR)


def test_get_and_update_row(clean_bookmarks):
    row = _insert()
    fetched = crud.get_row("bookmarks", "uid", row["uid"])
    assert fetched["uid"] == row["uid"]
    updated = crud.update_row(
        "bookmarks", "uid", row["uid"], {"target_uid": "t2"}, ACTOR
    )
    assert updated["target_uid"] == "t2"


def test_update_cannot_change_uid(clean_bookmarks):
    row = _insert()
    crud.update_row("bookmarks", "uid", row["uid"], {"uid": "hacked"}, ACTOR)
    assert get_table("bookmarks").find_one(uid="hacked") is None


def test_soft_delete_then_restore(clean_bookmarks):
    row = _insert()
    outcome = crud.delete_row("bookmarks", "uid", row["uid"], ACTOR)
    assert outcome["mode"] == "soft"
    live, _ = crud.list_rows("bookmarks", filters={"user_uid": MARK})
    assert live == []
    deleted, _ = crud.list_rows(
        "bookmarks", filters={"user_uid": MARK}, include_deleted=True
    )
    assert len(deleted) == 1
    restored = crud.restore_row("bookmarks", "uid", row["uid"], ACTOR)
    assert restored["deleted_at"] is None


def test_hard_delete_purges(clean_bookmarks):
    row = _insert()
    outcome = crud.delete_row("bookmarks", "uid", row["uid"], ACTOR, hard=True)
    assert outcome["mode"] == "hard"
    assert get_table("bookmarks").find_one(uid=row["uid"]) is None


def test_list_rows_caps_limit(clean_bookmarks):
    rows, _ = crud.list_rows("bookmarks", limit=99999)
    assert isinstance(rows, list)


def test_schema_reports_soft_delete(local_db):
    schema = crud.schema("bookmarks")
    assert schema["soft_delete"] is True
    assert any(c["name"] == "uid" for c in schema["columns"])


def test_bad_key_raises(local_db):
    with pytest.raises(DbApiError):
        crud.get_row("bookmarks", "no_such_key", "x")
