from unittest import mock
from unittest.mock import MagicMock, patch
from zulip_bots.test_lib import BotTestCase

class TestXkcdBot(BotTestCase):
    bot_name = "xkcd"

    def test_latest_command(self) -> None:
        bot_response = ("#1866: **Russell's Teapot**\n"
                        "[Unfortunately, NASA regulations state that Bertrand Russell-related "
                        "payloads can only be launched within launch vehicles which do not launch "
                        "themselves.](https://imgs.xkcd.com/comics/russells_teapot.png)")
        with self.mock_http_conversation('test_latest'):
            self.verify_reply('latest', bot_response)

    def test_random_command(self) -> None:
        bot_response = ("#1800: **Chess Notation**\n"
                        "[I've decided to score all my conversations using chess win-loss "
                        "notation. (??)](https://imgs.xkcd.com/comics/chess_notation.png)")
        with self.mock_http_conversation('test_random'):
            # Mock randint function.
            with patch('zulip_bots.bots.xkcd.xkcd.random.randint') as randint:
                mock_rand_value = mock.MagicMock()
                mock_rand_value.return_value = 1800
                randint.return_value = mock_rand_value.return_value
                self.verify_reply('random', bot_response)

    def test_numeric_comic_id_command_1(self) -> None:
        bot_response = ("#1: **Barrel - Part 1**\n[Don't we all.]"
                        "(https://imgs.xkcd.com/comics/barrel_cropped_(1).jpg)")
        with self.mock_http_conversation('test_specific_id'):
            self.verify_reply('1', bot_response)

    @mock.patch('logging.exception')
    def test_invalid_comic_ids(self, mock_logging_exception: mock.Mock) -> None:
        invalid_id_txt = "Sorry, there is likely no xkcd comic strip with id: #"

        for comic_id, fixture in (('0', 'test_not_existing_id_2'),
                                  ('999999999', 'test_not_existing_id')):
            with self.mock_http_conversation(fixture):
                self.verify_reply(comic_id, invalid_id_txt + comic_id)

    def test_help_responses(self) -> None:
        help_txt = "xkcd bot supports these commands:"
        err_txt  = "xkcd bot only supports these commands, not `{}`:"
        commands = '''
* `@xkcd help` to show this help message.
* `@xkcd latest` to fetch the latest comic strip from xkcd.
* `@xkcd random` to fetch a random comic strip from xkcd.
* `@xkcd <comic id>` to fetch a comic strip based on `<comic id>` e.g `@xkcd 1234`.'''
        self.verify_reply('', err_txt.format('') + commands)
        self.verify_reply('help', help_txt + commands)
        # Example invalid command
        self.verify_reply('x', err_txt.format('x') + commands)
