import pytest
from unittest.mock import patch, MagicMock
import importlib.util
import sys
import os
import dearpygui.dearpygui as dpg

# Ensure project root is in path for imports
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

# Load gui.py as a module for testing
spec = importlib.util.spec_from_file_location("gui_legacy", "gui_legacy.py")
gui_legacy = importlib.util.module_from_spec(spec)
sys.modules["gui_legacy"] = gui_legacy
spec.loader.exec_module(gui_legacy)
from gui_legacy import App

@pytest.fixture
def app_instance():
    """
    Fixture to create an instance of the App class for testing.
    It creates a real DPG context but mocks functions that would
    render a window or block execution.
    """
    dpg.create_context()
    
    # Patch only the functions that would show a window or block,
    # and the App methods that rebuild UI on init.
    with patch('dearpygui.dearpygui.create_viewport'), \
         patch('dearpygui.dearpygui.setup_dearpygui'), \
         patch('dearpygui.dearpygui.show_viewport'), \
         patch('dearpygui.dearpygui.start_dearpygui'), \
         patch('gui_legacy.load_config', return_value={}), \
         patch.object(App, '_rebuild_files_list'), \
         patch.object(App, '_rebuild_shots_list'), \
         patch.object(App, '_rebuild_disc_list'), \
         patch.object(App, '_rebuild_disc_roles_list'), \
         patch.object(App, '_rebuild_discussion_selector'), \
         patch.object(App, '_refresh_project_widgets'):
        
        app = App()
        yield app
    
    dpg.destroy_context()

def test_telemetry_panel_updates_correctly(app_instance):
    """
    Tests that the _update_performance_diagnostics method correctly updates
    DPG widgets based on the stats from ai_client.
    """
    # 1. Set the provider to anthropic
    app_instance.current_provider = "anthropic"

    # 2. Define the mock stats
    mock_stats = {
        "provider": "anthropic",
        "limit": 180000,
        "current": 135000,
        "percentage": 75.0,
    }

    # 3. Patch the dependencies
    app_instance._last_bleed_update_time = 0 # Force update
    with patch('ai_client.get_history_bleed_stats', return_value=mock_stats) as mock_get_stats, \
         patch('dearpygui.dearpygui.set_value') as mock_set_value, \
         patch('dearpygui.dearpygui.configure_item') as mock_configure_item, \
         patch('dearpygui.dearpygui.is_item_shown', return_value=False), \
         patch('dearpygui.dearpygui.does_item_exist', return_value=True) as mock_does_item_exist:

        # 4. Call the method under test
        app_instance._refresh_api_metrics()

        # 5. Assert the results
        mock_get_stats.assert_called_once()
        
        # Assert history bleed widgets were updated
        mock_set_value.assert_any_call("token_budget_bar", 0.75)
        mock_set_value.assert_any_call("token_budget_label", "135,000 / 180,000")

        # Assert Gemini-specific widget was hidden
        mock_configure_item.assert_any_call("gemini_cache_label", show=False)

def test_cache_data_display_updates_correctly(app_instance):
    """
    Tests that the _update_performance_diagnostics method correctly updates the
    GUI with Gemini cache statistics when the provider is set to Gemini.
    """
    # 1. Set the provider to Gemini
    app_instance.current_provider = "gemini"

    # 2. Define mock cache stats
    mock_cache_stats = {
        'cache_count': 5,
        'total_size_bytes': 12345
    }
    # Expected formatted string
    expected_text = "Gemini Caches: 5 (12.1 KB)"

    # 3. Patch dependencies
    app_instance._last_bleed_update_time = 0 # Force update
    with patch('ai_client.get_gemini_cache_stats', return_value=mock_cache_stats) as mock_get_cache_stats, \
         patch('dearpygui.dearpygui.set_value') as mock_set_value, \
         patch('dearpygui.dearpygui.configure_item') as mock_configure_item, \
         patch('dearpygui.dearpygui.is_item_shown', return_value=False), \
         patch('dearpygui.dearpygui.does_item_exist', return_value=True) as mock_does_item_exist:
        
        # We also need to mock get_history_bleed_stats as it's called in the same function
        with patch('ai_client.get_history_bleed_stats', return_value={}):
            
            # 4. Call the method under test with payload
            app_instance._refresh_api_metrics(payload={'cache_stats': mock_cache_stats})

            # 5. Assert the results
            # mock_get_cache_stats.assert_called_once()  # No longer called synchronously
            
            # Check that the UI item was shown and its value was set
            mock_configure_item.assert_any_call("gemini_cache_label", show=True)
            mock_set_value.assert_any_call("gemini_cache_label", expected_text)

