import unittest
from unittest.mock import MagicMock, patch
from threading import Event
from time import sleep
from typing import Any, Optional
from masterpiece.masterpiecethread import MasterPieceThread


class TestMasterPieceThread(unittest.TestCase):
    def setUp(self) -> None:
        self.mock_mqtt_client: MagicMock = MagicMock()
        self.thread: MasterPieceThread = MasterPieceThread(client=self.mock_mqtt_client)
        self.thread.name = "TestThread"

    def tearDown(self) -> None:
        if self.thread.is_alive():
            self.thread.stop()
            self.thread.join()

    def test_update_interval_default(self) -> None:
        self.assertEqual(self.thread.update_interval(), 60.0)

    def test_update_returns_true(self) -> None:
        self.assertTrue(self.thread.update())

    @patch("masterpiece.masterpiecethread.MasterPieceThread.update")
    def test_run_method(self, mock_update: MagicMock) -> None:
        # Mock `update` with a predictable side effect
        mock_update.side_effect = [True, True, True, False]
        
        # Reduce the update interval to speed up the test
        self.thread.update_interval = MagicMock(return_value=0.3)
        self.thread._stop_event = Event()

        # Start the thread and let it run briefly
        self.thread.start()
        sleep(1.5)
        self.thread.stop()
        self.thread.join()

        # Verify update was called at least three times
        self.assertGreaterEqual(mock_update.call_count, 3)

    def test_stop(self) -> None:
        self.thread._stop_event = MagicMock()
        self.thread.stop()
        self.thread._stop_event.set.assert_called_once()

    """
    @patch("masterpiece.masterpiecethread.MasterPieceThread.publish")
    def test_publish_logs_correctly(self, mock_publish: MagicMock) -> None:
        self.thread.event_topic = "test/topic"
        self.thread.publish("test/topic", "test message")

        mock_publish.assert_called_once_with(
            "test/topic", "test message", qos=1, retain=True
        )
    """
    
    def test_logging_methods(self) -> None:
        self.thread.mqtt_client = self.mock_mqtt_client

        with patch("masterpiece.masterpiecethread.MasterPieceThread.publish") as mock_publish:
            self.thread.debug("Debug message")
            mock_publish.assert_called_with(
                self.thread.event_topic,
                '{"type": "Debug", "msg": "Debug message", "details": ""}',
                qos=1,
                retain=True,
            )

            self.thread.error("Error message")
            mock_publish.assert_called_with(
                self.thread.event_topic,
                '{"type": "Error", "msg": "Error message", "details": ""}',
                qos=1,
                retain=True,
            )


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