# import sys
# from unittest.mock import MagicMock


# # Patch LocalHttpServerThread globally before importing App
# class DummyLocalHttpServerThread:
#     def __init__(self, *args, **kwargs):
#         pass

#     def start(self):
#         pass

#     def stop(self):
#         pass

#     def wait(self):
#         pass


# import airunner.gui.widgets.llm.local_http_server

# airunner.gui.widgets.llm.local_http_server.LocalHttpServerThread = (
#     DummyLocalHttpServerThread
# )

import unittest
from unittest.mock import patch, MagicMock, PropertyMock, mock_open
import signal
import sys

from airunner.app import App
from PySide6 import QtCore


class TestApp(unittest.TestCase):
    def setUp(self):
        """Set up common test variables."""
        self.mock_main_window_class = MagicMock()
        self.mock_window_class_params = {}
        # Ensure .api.llm is always a MagicMock with required methods
        self.mock_llm = MagicMock()
        self.mock_llm.send_request = MagicMock()
        self.mock_llm.reload_rag = MagicMock()
        self.mock_llm.clear_history = MagicMock()
        self.mock_llm.converation_deleted = MagicMock()
        self.mock_api = MagicMock(llm=self.mock_llm, nodegraph=MagicMock())

    @patch("airunner.app.QApplication.setAttribute")
    @patch("airunner.app.QApplication.instance")
    @patch("sys.exit")
    @patch("airunner.app.LocalHttpServerThread")
    @patch("airunner.app.MainWindow")
    def test_initialization_with_gui(
        self,
        mock_main_window,
        mock_http_server,
        mock_exit,
        mock_instance,
        mock_set_attr,
    ):
        mock_instance.return_value.exec.return_value = 0
        # Patch the MainWindow so that any access to .api or .nodegraph is safe
        mock_window_instance = MagicMock()
        mock_window_instance.api = self.mock_api
        mock_main_window.return_value = mock_window_instance
        app = App(no_splash=True, initialize_gui=True)
        self.assertIsNotNone(app.app)
        self.assertTrue(mock_set_attr.called)
        self.assertTrue(mock_instance.called)
        mock_exit.assert_called_once_with(0)

    @patch("airunner.app_installer.AppInstaller.start", return_value=None)
    @patch("airunner.app_installer.AppInstaller.__init__", return_value=None)
    @patch(
        "airunner.app.ApplicationSettings.objects.first",
        return_value=MagicMock(run_setup_wizard=True),
    )
    def test_run_setup_wizard(
        self,
        mock_appsettings_first,
        mock_appinstaller_init,
        mock_appinstaller_start,
    ):
        """Test the run_setup_wizard method."""
        App.run_setup_wizard()
        mock_appinstaller_init.assert_called_once()

    @patch("airunner.app.QPainter", new_callable=MagicMock)
    @patch("airunner.app.QPixmap", new_callable=MagicMock)
    @patch("airunner.app.QSplashScreen", new_callable=MagicMock)
    @patch("airunner.app.QApplication", new_callable=MagicMock)
    @patch("sys.exit")
    @patch("airunner.app.QGuiApplication.screens", return_value=[MagicMock()])
    @patch("airunner.app.LocalHttpServerThread")
    def test_run_with_splash(
        self,
        mock_http_server,
        mock_screens,
        mock_exit,
        mock_qapplication,
        mock_splash_screen,
        mock_qpixmap,
        mock_qpainter,
    ):
        """Test the run method with splash screen enabled."""
        mock_qapplication.return_value.exec.return_value = 0
        mock_splash_instance = MagicMock()
        mock_splash_screen.return_value = mock_splash_instance
        mock_qpixmap.return_value = MagicMock()
        mock_qpainter.return_value = MagicMock()

        app = App(no_splash=False, initialize_gui=True)
        app.run()

        mock_splash_screen.assert_called_once()  # Ensure only one splash screen is created
        mock_splash_instance.show.assert_called_once()  # Ensure the splash screen is shown
        mock_splash_instance.showMessage.assert_called_once_with(
            "Loading AI Runner",
            QtCore.Qt.AlignmentFlag.AlignBottom
            | QtCore.Qt.AlignmentFlag.AlignCenter,
            QtCore.Qt.GlobalColor.white,
        )

    @patch("airunner.app.QSplashScreen.showMessage")
    def test_update_splash_message(self, mock_show_message):
        """Test the update_splash_message method."""
        mock_splash = MagicMock()
        App.update_splash_message(mock_splash, "Loading...")
        mock_splash.showMessage.assert_called_once_with(
            "Loading...",
            QtCore.Qt.AlignmentFlag.AlignBottom
            | QtCore.Qt.AlignmentFlag.AlignCenter,
            QtCore.Qt.GlobalColor.white,
        )

    @patch("airunner.app.os.path.isdir", return_value=True)
    @patch("airunner.app.LocalHttpServerThread")
    @patch("sys.exit")
    @patch("airunner.app.QApplication")
    @patch("airunner.app.MainWindow")
    def test_show_main_application(
        self,
        mock_main_window,
        mock_qapplication,
        mock_exit,
        mock_http_server,
        mock_isdir,
    ):
        """Test the show_main_application method."""
        app = App(initialize_gui=False)  # Prevent GUI from opening
        app.splash = mock_qapplication
        app.show_main_application(app)
        mock_main_window.assert_not_called()  # Ensure main window is not created
        mock_qapplication.finish.assert_not_called()  # Ensure splash screen is not finished


if __name__ == "__main__":
    unittest.main()
