from slackminion.slack.conversation import SlackConversation
from slackminion.tests.fixtures import *

TEST_CONVERSATION = {
    'id': 'C02KT31H9GX',
    'name': 'TEST-channel',
    'is_channel': True,
    'is_group': False,
    'is_im': False,
    'is_mpim': False,
    'is_private': False,
    'name_normalized': 'test-channel',
    'topic': {'value': '', 'creator': '', 'last_set': 0},
    'previous_names': ['old-test-channel-name', 'some-other-name'],
    'priority': 0
}
TEST_CONVERSATION_UNNAMED = {
    'id': 'C02KT31H9GX',
    'is_channel': True,
    'is_group': False,
    'is_im': False,
    'is_mpim': False,
    'is_private': False,
    'topic': {'value': '', 'creator': '', 'last_set': 0},
    'priority': 0
}


class TestConversation(unittest.TestCase):

    def setUp(self):
        self.api_client = mock.Mock()
        self.object = SlackConversation(TEST_CONVERSATION, self.api_client)
        self.assertEqual(self.object.conversation, TEST_CONVERSATION)

    def test_missing_names(self):
        conversation = SlackConversation(TEST_CONVERSATION_UNNAMED, self.api_client)
        expected_names = []
        self.assertEqual(conversation.all_names, expected_names)

        new_name = TEST_CONVERSATION.get('name')
        TEST_CONVERSATION_UNNAMED['name'] = new_name
        conversation = SlackConversation(TEST_CONVERSATION_UNNAMED, self.api_client)
        expected_names = [new_name]
        self.assertEqual(conversation.all_names, expected_names)

        normalized_name = TEST_CONVERSATION.get('name_normalized')
        TEST_CONVERSATION_UNNAMED['name_normalized'] = normalized_name
        conversation = SlackConversation(TEST_CONVERSATION_UNNAMED, self.api_client)
        expected_names = [new_name, normalized_name]
        self.assertEqual(conversation.all_names, expected_names)

        previous_names = TEST_CONVERSATION.get('previous_names')
        TEST_CONVERSATION_UNNAMED['previous_names'] = previous_names
        conversation = SlackConversation(TEST_CONVERSATION_UNNAMED, self.api_client)
        expected_names = [new_name, normalized_name] + previous_names
        self.assertEqual(conversation.all_names, expected_names)

    def test_all_names(self):
        expected_names = [TEST_CONVERSATION['name'], TEST_CONVERSATION['name_normalized']] \
                         + TEST_CONVERSATION['previous_names']
        self.assertEqual(self.object.all_names, expected_names)

    def test_topic(self):
        self.assertEqual(self.object.topic, TEST_CONVERSATION['topic']['value'])
        new_topic = 'new topic'
        self.object.topic = new_topic
        self.assertEqual(self.object.topic, new_topic)
        self.api_client.conversations_setTopic.assert_called_with(channel=self.object.id, topic=new_topic)

    def test_getattr_accessor(self):
        self.assertEqual(self.object.is_private, TEST_CONVERSATION['is_private'])

    def test_channel_id(self):
        self.assertEqual(self.object.channel, TEST_CONVERSATION['id'])
        self.assertEqual(self.object.channel_id, TEST_CONVERSATION['id'])

    @async_test
    async def test_load_conversation(self):
        self.api_client.conversations_info = AsyncMock()
        self.api_client.conversations_info.coro.return_value = {'channel': TEST_CONVERSATION}
        self.object.conversation = {}
        await self.object.load(TEST_CONVERSATION['id'])
        self.api_client.conversations_info.assert_called_with(channel=TEST_CONVERSATION['id'])
        self.assertEqual(self.object.conversation, TEST_CONVERSATION)

    @async_test
    async def test_load_conversation_no_data(self):
        self.api_client.conversations_info = AsyncMock()
        self.api_client.conversations_info.coro.return_value = None
        self.object.conversation = {}
        with self.assertRaises(RuntimeError):
            await self.object.load(TEST_CONVERSATION['id'])

    def test_load_extra_attributes(self):
        self.object.conversation = {'id': TEST_CONVERSATION['id']}
        self.api_client.conversations_info.return_value = {'channel': TEST_CONVERSATION}
        self.object._load_extra_attributes()
        print(self.api_client.mock_calls)
        self.api_client.conversations_info.assert_called_with(channel=self.object.channel_id)
        self.assertEqual(self.object.conversation, TEST_CONVERSATION)

    def test_misc_methods(self):
        self.assertEqual(self.object.get_channel(), self.object)
        self.assertEqual(self.object.formatted_name, f'<#{self.object.id}|{self.object.name}>')
        self.assertEqual(f'{self.object}', self.object.formatted_name)
