# Generated by CodiumAI
# Dependencies:
# pip install pytest-mock
import pytest

from pyadtpulse.alarm_panel import ADTPulseAlarmPanel
from pyadtpulse.const import DEFAULT_API_HOST
from pyadtpulse.gateway import ADTPulseGateway
from pyadtpulse.pulse_connection import ADTPulseConnection
from pyadtpulse.site import ADTPulseSite
from pyadtpulse.zones import ADTPulseZones


class TestADTPulseSite:
    # can create an instance of ADTPulseSite with pulse_connection, site_id, and name
    def test_create_instance(self):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        assert site._pulse_connection == pulse_connection
        assert site._id == "site_id"
        assert site._name == "site_name"
        assert site._last_updated == 0
        assert isinstance(site._zones, ADTPulseZones)
        # assert isinstance(site._site_lock, RLock) or isinstance(site._site_lock, DebugRLock)
        assert isinstance(site._alarm_panel, ADTPulseAlarmPanel)
        assert isinstance(site._gateway, ADTPulseGateway)

    # can get the id of the site
    def test_get_id(self):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        assert site.id == "site_id"

    # can get the name of the site
    def test_get_name(self):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        assert site.name == "site_name"

    # can get the last_updated timestamp of the site
    def test_get_last_updated(self):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        assert site.last_updated == 0

    # can get the site_lock of the site
    """
    @pytest.mark.asyncio
    def test_get_site_lock(self):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        assert isinstance(site.site_lock, RLock) or isinstance(site.site_lock, DebugRLock)
        """

    # can arm the system home
    def test_arm_home(self, mocker):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        site.arm_home() == True

    # Raises a RuntimeError if no control panels exist when trying to arm the system home
    def test_arm_home_no_control_panels(self, mocker):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        with pytest.raises(RuntimeError):
            site.arm_home()

    # Raises a RuntimeError if no zones exist when trying to get the zones of the site as a list of ADTPulseFlattendZone objects
    def test_get_zones_list_no_zones(self, mocker):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        with pytest.raises(RuntimeError):
            site.zones

    # Raises a RuntimeError if no zones exist when trying to get the zones of the site as a dictionary of ADTPulseZone objects
    def test_get_zones_dict_no_zones(self, mocker):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        with pytest.raises(RuntimeError):
            site.zones_as_dict

    # can arm the system away
    @pytest.mark.asyncio
    def test_arm_away(self, event_loop):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        pulse_connection.loop = event_loop
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        assert site.arm_away() is True

    # can disarm the system
    def test_disarm_system_fixed(self, mocker):
        pulse_connection = mocker.Mock(spec=ADTPulseConnection)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")

        with pytest.raises(RuntimeError):
            site.disarm()

        site._alarm_panel = mocker.Mock(spec=ADTPulseAlarmPanel)
        site._alarm_panel.disarm.return_value = True

        assert site.disarm() == True

    # can asynchronously arm the system home
    @pytest.mark.asyncio
    async def test_async_arm_home(self, mocker):
        pulse_connection = mocker.Mock(spec=ADTPulseConnection)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")

        site._alarm_panel = mocker.Mock(spec=ADTPulseAlarmPanel)
        site._alarm_panel.async_arm_home.return_value = True

        assert await site.async_arm_home() == True

    # can asynchronously arm the system away
    @pytest.mark.asyncio
    async def test_async_arm_away(self, mocker):
        pulse_connection = mocker.Mock(spec=ADTPulseConnection)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        site._alarm_panel = mocker.Mock(spec=ADTPulseAlarmPanel)
        site._alarm_panel.async_arm_away.return_value = True

        assert await site.async_arm_away() is True

    # can asynchronously disarm the system
    @pytest.mark.asyncio
    async def test_disarm_system(self, mocker):
        # Arrange
        pulse_connection = mocker.Mock()
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        alarm_control_panel = mocker.Mock()
        site.alarm_control_panel = alarm_control_panel

        # Act
        result = await site.async_disarm()

        # Assert
        alarm_control_panel.disarm.assert_called_once_with(pulse_connection)
        assert result == alarm_control_panel.disarm.return_value

    # can get the zones of the site as a list of ADTPulseFlattendZone objects
    def test_get_zones_as_list(self, mocker):
        # Arrange
        pulse_connection = mocker.Mock()
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        zones = mocker.Mock()
        site._zones = zones
        flattened_zones = mocker.Mock()
        zones.flatten.return_value = flattened_zones

        # Act
        result = site.zones

        # Assert
        zones.flatten.assert_called_once_with()
        assert result == flattened_zones

    # can get the zones of the site as a dictionary of ADTPulseZone objects
    def test_get_zones_as_dict(self, mocker):
        # Arrange
        pulse_connection = mocker.Mock()
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        zones = mocker.Mock()
        site._zones = zones

        # Act
        result = site.zones_as_dict

        # Assert
        assert result == zones

    # can get the alarm control panel of the site
    def test_get_alarm_control_panel(self):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        assert isinstance(site.alarm_control_panel, ADTPulseAlarmPanel)

    # can get the gateway of the site
    def test_get_gateway(self):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        assert isinstance(site.gateway, ADTPulseGateway)

    # raises a RuntimeError if no control panels exist when trying to arm the system home
    def test_raise_runtime_error_when_no_control_panels_exist(self):
        pulse_connection = ADTPulseConnection(DEFAULT_API_HOST)
        site = ADTPulseSite(pulse_connection, "site_id", "site_name")
        with pytest.raises(RuntimeError):
            site.arm_home()
