#!/usr/bin/env python3
from __future__ import annotations

import sympy as sp
from sympy.utilities.lambdify import lambdify

import jarvis_operas
import jarvis_operas.integration as integration
from jarvis_operas.integration import build_register_dicts, build_sympy_dicts
from jarvis_operas.registry import OperatorRegistry


def test_build_register_dicts_returns_full_name_to_callable_only() -> None:
    registry = OperatorRegistry()
    registry.register("LZSI2024", lambda x: x * 2.0, namespace="dmdd")

    mapping = build_register_dicts(registry)
    assert callable(mapping["dmdd.LZSI2024"])
    assert set(mapping.keys()) == {"dmdd.LZSI2024"}


def test_build_sympy_dicts_for_namespace_function_parsing_and_eval() -> None:
    registry = OperatorRegistry()
    registry.register("LZSI2024", lambda x: x * 2.0, namespace="dmdd")
    registry.register("add", lambda x, y: x + y, namespace="math")

    mapping = build_register_dicts(registry)
    func_locals, numeric_funcs = build_sympy_dicts(mapping, namespaces=["dmdd"])

    expr = sp.sympify("dmdd.LZSI2024(mchi)", locals=func_locals)
    num_expr = lambdify(["mchi"], expr, modules=[numeric_funcs, "numpy"])

    assert float(num_expr(95.0)) == 190.0
    assert "math" not in func_locals


def test_refresh_register_dicts_updates_module_level_sympy_dicts(monkeypatch) -> None:
    monkeypatch.setattr(
        integration,
        "build_register_dicts",
        lambda registry=None: {"dmdd.LZSI2024": lambda x: x + 1.0},
    )

    integration.refresh_register_dicts()

    expr = sp.sympify("dmdd.LZSI2024(mchi)", locals=integration.func_locals)
    num_expr = lambdify(["mchi"], expr, modules=[integration.numeric_funcs, "numpy"])
    assert float(num_expr(2.0)) == 3.0


def test_refresh_register_dicts_keeps_package_level_dict_refs_fresh(monkeypatch) -> None:
    monkeypatch.setattr(
        integration,
        "build_register_dicts",
        lambda registry=None: {"dmdd.LZSI2024": lambda x: x},
    )

    package_func_locals = jarvis_operas.func_locals
    package_numeric_funcs = jarvis_operas.numeric_funcs
    jarvis_operas.refresh_register_dicts()

    assert package_func_locals is jarvis_operas.func_locals
    assert package_numeric_funcs is jarvis_operas.numeric_funcs
    assert "dmdd" in package_func_locals
    assert package_numeric_funcs
