# -*- coding: utf-8 -*-
import unittest
from datetime import datetime
from unittest.mock import call
from uuid import uuid4, UUID

from mock import patch, MagicMock

from alamo_worker.alerter.backend.cassandra import (
    CassandraDriver, SELECT_QUERY, INSERT_QUERY, INSERT_SERVICE_QUERY,
    AsyncCassandraDriver
)
from alamo_worker.alerter.utils import CachedResult
from tests.base import run_async


class CassandraDriverTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.check_uuid = str(uuid4())
        cls.trigger_uuid = str(uuid4())

    @patch('alamo_worker.alerter.backend.cassandra.Cluster')
    @patch('alamo_worker.alerter.backend.cassandra.PlainTextAuthProvider')
    def setUp(self, auth_mock, cluster_mock):
        session_mock = MagicMock()
        cluster_mock.connect = MagicMock(return_value=session_mock)
        self.trigger = dict(
            id=self.trigger_uuid,
            uuid=str(uuid4()),
            severity='WARNING',
            enabled=True,
            result=dict(status=0, message='')
        )

        self.driver = CassandraDriver(
            contact_points=[''],
            username='username',
            password='password',
            keyspace='test'
        )

    def test_prepared_statements(self):
        expected_calls = [call(SELECT_QUERY), call(INSERT_QUERY),
                          call(INSERT_SERVICE_QUERY)]
        self.driver._connect()
        self.driver._session.prepare.assert_has_calls(
            expected_calls, any_order=True
        )

    def test_get_result_method(self):
        self.driver.get_result(self.check_uuid, self.trigger_uuid, 10)
        self.driver._connect()
        self.driver._session.execute.assert_called_once_with(
            self.driver._save_query_stmt,
            (UUID(self.check_uuid), UUID(self.trigger_uuid), 10),
            execution_profile='normal'
        )

    def test_save_result_method(self):
        _now = datetime.now()
        self.driver._connect()
        self.driver.save_result(
            self.check_uuid, self.trigger, _now, _now, _now, False, '999'
        )

        self.assertTrue(self.driver._session.execute.called)


class DummyRow(object):
    def __init__(self, *, status, alert_sent, message):
        self.status = status
        self.alert_sent = alert_sent
        self.message = message


class AsyncCassandraDriverTestCase(unittest.TestCase):
    @classmethod
    def 
(cls):
        cls.check_uuid = uuid4()
        cls.trigger_uuid = uuid4()

    @patch.object(AsyncCassandraDriver, '_connect')
    def setUp(self, mock_connect):
        async def _execute(*args, **kwargs):
            return [
                DummyRow(status=0, alert_sent=False, message='')
            ]
        driver = AsyncCassandraDriver(
            contact_points=[''],
            username='username',
            password='password',
            keyspace='test')
        driver._session = MagicMock()
        driver._session.execute_future.side_effect = _execute
        self.driver = driver
        self.trigger = dict(
            id=self.trigger_uuid,
            uuid=str(uuid4()),
            severity='WARNING',
            enabled=True,
            result=dict(status=0, message='')
        )

    def test_get_result(self):
        result = run_async(
            self.driver.get_result(
                str(self.check_uuid), str(self.trigger_uuid), 10)
        )

        self.driver._session.execute_future.assert_called_once_with(
            self.driver._retrieve_query_stmt, (
                self.check_uuid,
                self.trigger_uuid,
                10
            ),
            execution_profile='normal'
        )
        expected = CachedResult(0, 0, False, '')
        self.assertEqual(result, [expected])

    def test_save_result_method(self):
        _now = datetime.now()
        self.driver._save_query_stmt = MagicMock()
        self.driver._save_service_query_stmt = MagicMock()

        run_async(self.driver.save_result(
            str(self.check_uuid), self.trigger, _now, _now, _now, False, '999'
        ))

        self.assertTrue(self.driver._session.execute_future.called)

setUpClass