import threading

from grayloghelper import (
    DynamicLogFieldsFilter,
    clear_log_fields,
    log_fields,
    set_log_fields,
)


def test_filter_copies_fields_to_record(make_record):
    set_log_fields(tenant_id="t-1", user_id=42)
    rec = make_record()
    DynamicLogFieldsFilter().filter(rec)
    assert rec.tenant_id == "t-1"
    assert rec.user_id == 42


def test_filter_is_noop_without_attribute(make_record):
    rec = make_record()
    DynamicLogFieldsFilter().filter(rec)
    assert not hasattr(rec, "tenant_id")


def test_filter_returns_one(make_record):
    rec = make_record()
    assert DynamicLogFieldsFilter().filter(rec) == 1


def test_set_log_fields_merges(make_record):
    set_log_fields(a=1)
    set_log_fields(b=2)
    rec = make_record()
    DynamicLogFieldsFilter().filter(rec)
    assert rec.a == 1
    assert rec.b == 2


def test_clear_log_fields_by_name(make_record):
    set_log_fields(a=1, b=2)
    clear_log_fields("a")
    rec = make_record()
    DynamicLogFieldsFilter().filter(rec)
    assert not hasattr(rec, "a")
    assert rec.b == 2


def test_clear_log_fields_all_removes_attribute():
    set_log_fields(a=1)
    clear_log_fields()
    assert not hasattr(threading.current_thread(), "_edp_log_fields")


def test_clear_unknown_name_is_silent():
    set_log_fields(a=1)
    clear_log_fields("does_not_exist")
    assert threading.current_thread()._edp_log_fields == {"a": 1}


def test_clear_when_nothing_set_is_silent():
    clear_log_fields()
    clear_log_fields("x")  # also fine


def test_log_fields_context_manager_restores_previous_state(make_record):
    set_log_fields(outer="v1")
    with log_fields(inner="v2", outer="override"):
        rec_inside = make_record()
        DynamicLogFieldsFilter().filter(rec_inside)
        assert rec_inside.inner == "v2"
        assert rec_inside.outer == "override"

    rec_outside = make_record()
    DynamicLogFieldsFilter().filter(rec_outside)
    assert rec_outside.outer == "v1"
    assert not hasattr(rec_outside, "inner")


def test_log_fields_context_manager_without_previous_state():
    with log_fields(a=1):
        assert threading.current_thread()._edp_log_fields == {"a": 1}
    assert not hasattr(threading.current_thread(), "_edp_log_fields")


def test_log_fields_context_manager_restores_on_exception():
    set_log_fields(outer="v1")
    try:
        with log_fields(outer="override"):
            raise RuntimeError("boom")
    except RuntimeError:
        pass
    assert threading.current_thread()._edp_log_fields == {"outer": "v1"}


def test_log_fields_nests():
    with log_fields(a=1):
        with log_fields(b=2, a="override"):
            assert threading.current_thread()._edp_log_fields == {"a": "override", "b": 2}
        assert threading.current_thread()._edp_log_fields == {"a": 1}
