import threading
from concurrent.futures import ThreadPoolExecutor

from grayloghelper import (
    DynamicLogFieldsFilter,
    build_thread_name_initializer,
    set_log_fields,
)


def _run_in_pool(fn, n=1):
    initializer = build_thread_name_initializer(threading.current_thread())
    with ThreadPoolExecutor(max_workers=n, initializer=initializer) as ex:
        return list(ex.map(fn, range(n)))


def test_worker_name_carries_processor_and_request_id():
    threading.current_thread().name = "MessageProcessorThread$OrderProcessor$req-9"
    try:
        names = _run_in_pool(lambda _: threading.current_thread().name, n=2)
    finally:
        threading.current_thread().name = "MainThread"

    for name in names:
        assert name.startswith("MessageProcessorThreadPool_")
        assert name.endswith("$OrderProcessor$req-9")


def test_worker_inherits_context_name():
    threading.current_thread()._edp_context_name = "tenant-A"
    contexts = _run_in_pool(
        lambda _: getattr(threading.current_thread(), "_edp_context_name", None)
    )
    assert contexts == ["tenant-A"]


def test_worker_inherits_log_fields(make_record):
    set_log_fields(req_id="r-9", tenant="t-1")

    def emit_in_worker(_):
        rec = type(make_record())(
            name="logger",
            level=20,
            pathname="f.py",
            lineno=1,
            msg="m",
            args=(),
            exc_info=None,
        )
        DynamicLogFieldsFilter().filter(rec)
        return rec.req_id, rec.tenant

    results = _run_in_pool(emit_in_worker, n=3)
    assert results == [("r-9", "t-1")] * 3


def test_worker_log_fields_dict_is_isolated_from_parent():
    set_log_fields(req_id="r-9")

    def tamper(_):
        threading.current_thread()._edp_log_fields["req_id"] = "tampered"
        threading.current_thread()._edp_log_fields["new"] = "added-in-worker"

    _run_in_pool(tamper, n=1)

    # parent dict must be untouched
    assert threading.current_thread()._edp_log_fields == {"req_id": "r-9"}


def test_no_propagation_when_parent_has_nothing():
    """Parent has no context/log-fields → workers also have none."""
    def probe(_):
        t = threading.current_thread()
        return (
            hasattr(t, "_edp_context_name"),
            hasattr(t, "_edp_log_fields"),
        )

    results = _run_in_pool(probe, n=1)
    assert results == [(False, False)]
