"""
Unit tests for automatic time announcement behavior.
"""

import datetime
import importlib.util
from pathlib import Path
from unittest.mock import Mock


def _load_time_module():
    module_path = (
        Path(__file__).resolve().parents[2]
        / "src"
        / "fenrirscreenreader"
        / "commands"
        / "onHeartBeat"
        / "76000-time.py"
    )
    spec = importlib.util.spec_from_file_location("fenrir_time_command", module_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module


def _create_environment(output_manager):
    now = datetime.datetime.now()
    settings_manager = Mock()
    settings_manager.get_setting.side_effect = lambda section, setting: {
        ("time", "on_minutes"): str(now.minute).zfill(2),
        ("general", "date_format"): "%A, %B %d, %Y",
        ("general", "time_format"): "%I:%M%P",
    }[(section, setting)]
    settings_manager.get_setting_as_int.side_effect = lambda section, setting: {
        ("time", "delay_sec"): 0,
    }[(section, setting)]
    settings_manager.get_setting_as_bool.side_effect = lambda section, setting: {
        ("time", "enabled"): True,
        ("time", "present_date"): True,
        ("time", "present_time"): True,
        ("time", "interrupt"): False,
        ("time", "announce"): True,
    }[(section, setting)]

    return {
        "runtime": {
            "OutputManager": output_manager,
            "SettingsManager": settings_manager,
        }
    }


def test_time_announcement_lock_suppresses_second_instance(tmp_path):
    time_module = _load_time_module()
    lock_path = tmp_path / "time-announcement.lock"
    first_output = Mock(
        interrupt_output=Mock(),
        play_sound_icon=Mock(),
        present_text=Mock(),
    )
    second_output = Mock(
        interrupt_output=Mock(),
        play_sound_icon=Mock(),
        present_text=Mock(),
    )
    first_command = time_module.command()
    second_command = time_module.command()

    first_command.initialize(_create_environment(first_output))
    second_command.initialize(_create_environment(second_output))
    first_command._get_announcement_lock_path = lambda: str(lock_path)
    second_command._get_announcement_lock_path = lambda: str(lock_path)
    first_command.last_time -= datetime.timedelta(hours=1)
    second_command.last_time -= datetime.timedelta(hours=1)

    first_command.run()
    second_command.run()

    first_output.play_sound_icon.assert_called_once_with("announce")
    first_output.present_text.assert_called()
    second_output.interrupt_output.assert_not_called()
    second_output.play_sound_icon.assert_not_called()
    second_output.present_text.assert_not_called()
