
import pytest
import responses

try:
    from unittest.mock import patch
except ImportError:
    from mock import patch

from instabot.api.config import API_URL

from .test_bot import TestBot
from .test_variables import (TEST_CAPTION_ITEM, TEST_COMMENT_ITEM, TEST_PHOTO_ITEM,
                             TEST_USERNAME_INFO_ITEM)


class TestBotFilter(TestBot):

    @responses.activate
    @pytest.mark.parametrize('media_id,total,max_per_day', [
        [111111, 1, 2],
        [111111, 2, 2],
        [111111, 3, 2],
        ['111111', 1, 2],
        ['111111', 2, 2],
        ['111111', 3, 2]])
    @patch('time.sleep', return_value=None)
    def test_unlike(self, patched_time_sleep, media_id, total, max_per_day):
        self.bot.total['unlikes'] = total
        self.bot.max_per_day['unlikes'] = max_per_day
        responses.add(
            responses.POST, "{api_url}media/{media_id}/unlike/".format(
                api_url=API_URL, media_id=media_id
            ), json="{'status': 'ok'}", status=200
        )
        _r = self.bot.unlike(media_id)
        test_r = _r if total < max_per_day else not _r
        test_unliked = self.bot.total['unlikes'] == total + 1 if total < max_per_day else self.bot.total['unlikes'] == total
        assert (test_r and test_unliked)

    @responses.activate
    @pytest.mark.parametrize('comment_id', [111111, '111111'])
    @patch('time.sleep', return_value=None)
    def test_unlike_comment(self, patched_time_sleep, comment_id):
        responses.add(
            responses.POST, "{api_url}media/{comment_id}/comment_unlike/".format(
                api_url=API_URL, comment_id=comment_id
            ), json="{'status': 'ok'}", status=200
        )
        _r = self.bot.unlike_comment(comment_id)
        assert _r

    @responses.activate
    @pytest.mark.parametrize('media_ids,total,max_per_day', [
        [[111111, 222222], 1, 3],
        [[111111, 222222], 2, 3],
        [[111111, 222222], 3, 3],
        [['111111', '222222'], 1, 3],
        [['111111', '222222'], 2, 3],
        [['111111', '222222'], 3, 3]])
    @patch('time.sleep', return_value=None)
    def test_unlike_medias(self, patched_time_sleep, media_ids, total, max_per_day):
        self.bot.total['unlikes'] = total
        self.bot.max_per_day['unlikes'] = max_per_day
        for media_id in media_ids:
            responses.add(
                responses.POST, "{api_url}media/{media_id}/unlike/".format(
                    api_url=API_URL, media_id=media_id
                ), json="{'status': 'ok'}", status=200
            )
        broken_items = self.bot.unlike_medias(media_ids)
        test_unliked = self.bot.total['unlikes'] == max_per_day
        test_broken = len(broken_items) == len(media_ids) - (max_per_day - total)
        assert (test_unliked and test_broken)

    @responses.activate
    @patch('time.sleep', return_value=None)
    def test_unlike_media_comments(self, patched_time_sleep):
        my_test_comment_items = []
        results = 5
        for i in range(results):
            my_test_comment_items.append(TEST_COMMENT_ITEM.copy())
            my_test_comment_items[i]['pk'] = TEST_COMMENT_ITEM['pk'] + i
            if i % 2:
                my_test_comment_items[i]['has_liked_comment'] = False
            else:
                my_test_comment_items[i]['has_liked_comment'] = True
        media_id = 1234567890
        response_data = {
            "caption": TEST_CAPTION_ITEM,
            "caption_is_edited": False,
            "comment_count": results,
            "comment_likes_enabled": True,
            "comments": my_test_comment_items,
            "has_more_comments": False,
            "has_more_headload_comments": False,
            "media_header_display": "none",
            "preview_comments": [],
            "status": "ok"
        }
        responses.add(
            responses.GET, '{api_url}media/{media_id}/comments/?'.format(
                api_url=API_URL, media_id=media_id), json=response_data, status=200)
        for my_test_comment_item in my_test_comment_items:
            responses.add(
                responses.POST, "{api_url}media/{comment_id}/comment_unlike/".format(
                    api_url=API_URL, comment_id=my_test_comment_item['pk']
                ), json="{'status': 'ok'}", status=200
            )
        broken_items = self.bot.unlike_media_comments(media_id)
        assert broken_items == []

    @responses.activate
    @patch('time.sleep', return_value=None)
    def test_unlike_user(self, patched_time_sleep):
        unliked_at_start = self.bot.total['unlikes']
        user_id = 1234567890
        response_data = {
            'status': 'ok',
            'user': TEST_USERNAME_INFO_ITEM
        }
        responses.add(
            responses.GET, '{api_url}users/{username}/usernameinfo/'.format(
                api_url=API_URL, username=user_id
            ), status=200, json=response_data)
        my_test_photo_items = []
        results = 5
        for i in range(results):
            my_test_photo_items.append(TEST_PHOTO_ITEM.copy())
            my_test_photo_items[i]['pk'] = TEST_PHOTO_ITEM['pk'] + i
            if i % 2:
                my_test_photo_items[i]['has_liked'] = False
            else:
                my_test_photo_items[i]['has_liked'] = True
        response_data = {
            "auto_load_more_enabled": True,
            "num_results": results,
            "status": "ok",
            "more_available": False,
            "items": my_test_photo_items
        }
        responses.add(
            responses.GET, '{api_url}feed/user/{user_id}/'.format(
                api_url=API_URL, user_id=user_id),
            json=response_data, status=200)
        for my_test_photo_item in my_test_photo_items:
            responses.add(
                responses.POST, "{api_url}media/{media_id}/unlike/".format(
                    api_url=API_URL, media_id=my_test_photo_item['pk']
                ), json="{'status': 'ok'}", status=200
            )
        broken_items = self.bot.unlike_user(user_id)
        test_unliked = self.bot.total['unlikes'] == unliked_at_start + len(my_test_photo_items)
        test_broken = broken_items == []
        assert (test_broken and test_unliked)
