import uuid

import pytest

from pydantic import BaseModel

from keble_helpers.common import stable_id_generator


def test_stable_id_generator_is_deterministic():
    payload_a = {"b": 2, "a": 1}
    payload_b = {"a": 1, "b": 2}

    id_a1 = stable_id_generator(payload=payload_a)
    id_a2 = stable_id_generator(payload=payload_a)
    id_b = stable_id_generator(payload=payload_b)

    assert id_a1 == id_a2
    assert id_a1 == id_b
    assert str(uuid.UUID(id_a1)) == id_a1


def test_stable_id_generator_changes_when_payload_changes():
    id_1 = stable_id_generator(payload={"a": 1, "b": 2})
    id_2 = stable_id_generator(payload={"a": 1, "b": 3})
    assert id_1 != id_2


@pytest.mark.parametrize(
    "key",
    [
        "created",
        "updated",
        "created_at",
        "updated_at",
        "createdAt",
        "updatedAt",
    ],
)
def test_stable_id_generator_rejects_timestamp_keys_by_default(key: str):
    with pytest.raises(ValueError) as excinfo:
        stable_id_generator(payload={"foo": "bar", key: "2024-01-01T00:00:00Z"})
    assert key in str(excinfo.value)


def test_stable_id_generator_allows_timestamp_keys_when_enabled():
    payload = {"foo": "bar", "created_at": "2024-01-01T00:00:00Z"}
    id_1 = stable_id_generator(payload=payload, allow_timestamp_keys=True)
    id_2 = stable_id_generator(
        payload={"created_at": payload["created_at"], "foo": payload["foo"]},
        allow_timestamp_keys=True,
    )
    assert id_1 == id_2


class _StableIdModel(BaseModel):
    a: int
    created: str
    updated_at: str


def test_stable_id_generator_accepts_base_model_and_ignores_timestamp_fields():
    m1 = _StableIdModel(a=1, created="t1", updated_at="t2")
    m2 = _StableIdModel(a=1, created="t3", updated_at="t4")
    assert stable_id_generator(payload=m1) == stable_id_generator(payload=m2)


def test_stable_id_generator_includes_timestamp_fields_when_enabled_for_base_model():
    m1 = _StableIdModel(a=1, created="t1", updated_at="t2")
    m2 = _StableIdModel(a=1, created="t3", updated_at="t4")
    assert stable_id_generator(
        payload=m1, allow_timestamp_keys=True
    ) != stable_id_generator(payload=m2, allow_timestamp_keys=True)
