# -*- coding: utf-8 -*-
from unittest import mock

from homehub_backend.lib import services
from homehub_backend.testing import services as testing_services


class Test_StartService:
    def teardown_method(self):
        testing_services.FakeGlobalService.reset()

    async def test_unknown_service(self, homehub_client):
        response = await homehub_client.post('/backend/rpc', json={
            'jsonrpc': '2.0',
            'id': 'testing',
            'method': 'services.start',
            'params': ['IDontExist', 'fake_instance', {'spam': True}],
        })
        assert response.status == 200

        data = await response.json()
        assert 'result' not in data
        assert data['error']['data'] == 'Unknown service: IDontExist'

    async def test_not_global(self, homehub_client):
        response = await homehub_client.post('/backend/rpc', json={
            'jsonrpc': '2.0',
            'id': 'testing',
            'method': 'services.start',
            'params': ['testing.FakeService', 'fake_instance', {'spam': True}],
        })
        assert response.status == 200

        data = await response.json()
        assert data['result'] == 'spam'

        service = homehub_client.server.app['SERVICES'].get(
            'testing.FakeService.fake_instance', None,
        )
        assert service is not None
        assert service.characteristics == {'spam': True}
        assert service.start.called is True

    async def test_global(self, homehub_client):
        response = await homehub_client.post('/backend/rpc', json={
            'jsonrpc': '2.0',
            'id': 'testing',
            'method': 'services.start',
            'params': [
                'testing.FakeGlobalService', 'fake_instance', {'spam': True},
            ],
        })
        assert response.status == 200

        data = await response.json()
        assert data['result'] == 'spam'

        service = homehub_client.server.app['SERVICES'].get(
            'testing.FakeGlobalService.None', None,
        )
        assert service is not None
        assert service.characteristics == {'spam': True}
        assert service.start.call_count == 1

    async def test_global_ensure_one_instance(self, homehub_client):
        response = await homehub_client.post('/backend/rpc', json={
            'jsonrpc': '2.0',
            'id': 'testing',
            'method': 'services.start',
            'params': [
                'testing.FakeGlobalService', 'fake_instance', {'spam': True},
            ],
        })
        assert response.status == 200

        service = homehub_client.server.app['SERVICES'].get(
            'testing.FakeGlobalService.None', None,
        )

        response = await homehub_client.post('/backend/rpc', json={
            'jsonrpc': '2.0',
            'id': 'testing',
            'method': 'services.start',
            'params': [
                'testing.FakeGlobalService', 'fake_instance', {'spam': True},
            ],
        })
        assert response.status == 200

        assert testing_services.FakeGlobalService.INSTANCE == service
        assert service.start.call_count == 1

    @mock.patch.object(testing_services.FakeService, 'make_data')
    async def test_data_error(self, mock_service_make_data, homehub_client):
        mock_service_make_data.return_value = services.ServiceData(
            exception=RuntimeError('TODO'),
        )

        response = await homehub_client.post('/backend/rpc', json={
            'jsonrpc': '2.0',
            'id': 'testing',
            'method': 'services.start',
            'params': ['testing.FakeService', 'fake_instance', {'spam': True}],
        })
        assert response.status == 200

        data = await response.json()
        assert 'result' not in data
        assert data['error']['data'] == 'TODO'
