import logging
import sys
import os
import unittest.mock as mock
from py.nodes.utils import nunchaku_load_lora

class _DummyTransformer:
    pass

class _DummyModelConfig:
    def __init__(self):
        self.unet_config = {"in_channels": 4}

class _DummyDiffusionModel:
    def __init__(self):
        self.model = _DummyTransformer()
        self.loras = []

class _DummyModelWrapper:
    def __init__(self):
        self.diffusion_model = _DummyDiffusionModel()
        self.model_config = _DummyModelConfig()

class _DummyModel:
    def __init__(self):
        self.model = _DummyModelWrapper()
    
    def clone(self):
        # This is what our legacy logic used via copy.deepcopy(model)
        # But in the new logic, copy_with_ctx returns the cloned model
        return self

def test_nunchaku_load_lora_legacy_fallback(monkeypatch, caplog):
    import folder_paths  # pyright: ignore[reportMissingImports]
    import copy
    
    dummy_model = _DummyModel()
    
    # Mock folder_paths and os.path.isfile to "find" the LoRA
    monkeypatch.setattr(folder_paths, "get_full_path", lambda folder, name: f"/fake/path/{name}", raising=False)
    monkeypatch.setattr(os.path, "isfile", lambda path: True if "/fake/path/" in path else False)
    
    # Mock to_diffusers to return a dummy state dict
    monkeypatch.setattr("py.nodes.utils.to_diffusers", lambda path: {})
    
    # Ensure copy_with_ctx is NOT found
    # model_wrapper.__class__.__module__ will be this module
    module_name = _DummyDiffusionModel.__module__
    if module_name in sys.modules:
        module = sys.modules[module_name]
        if hasattr(module, "copy_with_ctx"):
            monkeypatch.delattr(module, "copy_with_ctx")

    with caplog.at_level(logging.WARNING):
        result_model = nunchaku_load_lora(dummy_model, "some_lora", 0.8)
    
    assert "better LoRA support" in caplog.text
    assert len(result_model.model.diffusion_model.loras) == 1
    assert result_model.model.diffusion_model.loras[0][1] == 0.8

def test_nunchaku_load_lora_new_logic(monkeypatch):
    import folder_paths  # pyright: ignore[reportMissingImports]
    import os
    
    dummy_model = _DummyModel()
    model_wrapper = dummy_model.model.diffusion_model
    
    # Mock folder_paths and os.path.isfile
    monkeypatch.setattr(folder_paths, "get_full_path", lambda folder, name: f"/fake/path/{name}", raising=False)
    monkeypatch.setattr(os.path, "isfile", lambda path: True if "/fake/path/" in path else False)
    
    # Mock to_diffusers
    monkeypatch.setattr("py.nodes.utils.to_diffusers", lambda path: {})
    
    # Create the cloned objects that copy_with_ctx would return
    cloned_wrapper = _DummyDiffusionModel()
    cloned_model = _DummyModel()
    cloned_model.model.diffusion_model = cloned_wrapper
    
    # Define copy_with_ctx
    def mock_copy_with_ctx(wrapper):
        return cloned_wrapper, cloned_model
    
    # Inject copy_with_ctx into the module
    module_name = _DummyDiffusionModel.__module__
    module = sys.modules[module_name]
    monkeypatch.setattr(module, "copy_with_ctx", mock_copy_with_ctx, raising=False)
    
    result_model = nunchaku_load_lora(dummy_model, "new_lora", 0.7)
    
    assert result_model is cloned_model
    assert cloned_wrapper.loras == [("/fake/path/new_lora", 0.7)]
