"""Unittests for jira_scraper run module."""

import itertools
import logging
import unittest

import jira
import mock

from twitch import sandstorm

from code.justin.tv.dta.rockpaperscissors import event_bus
from code.justin.tv.dta.rockpaperscissors import jira as rps_jira
from code.justin.tv.dta.rockpaperscissors.proto.events import jira_scraper_pb2
from code.justin.tv.dta.rockpaperscissors.testutils import aws_lambda

import jira_scraper


logging.basicConfig(level=logging.INFO)


@mock.patch.object(rps_jira, 'JIRA', autospec=True)
@mock.patch.object(sandstorm, 'SandstormClient', autospec=True)
@mock.patch.object(event_bus, 'EventBus', autospec=True)
class TestCase(unittest.TestCase):

    @mock.patch('jira_scraper.GetProductionBugsCountByProject')
    @mock.patch('jira_scraper.GetIncidentIssuesCount')
    def testBasic(self, mock_get_incident_count, mock_get_prod_bugs, mock_bus,
                  mock_sandstorm, mock_jira):
        mock_get_incident_count.return_value = 10
        mock_get_prod_bugs.return_value = {'project': 5}

        jira_scraper.lambda_handler(
          aws_lambda.ScheduledLambdaEvent(),
          aws_lambda.Context('rockpaperscissors-development-lambda'))

        mock_get_incident_count.assert_called_once()
        mock_get_prod_bugs.assert_called_once()
        mock_bus_obj = mock_bus.return_value
        mock_bus_obj.PutEvent.assert_called_once()

        event = mock_bus_obj.PutEvent.call_args[0][0]
        self.assertEqual(event.type, 'JIRAScraperEvent')
        expected_event = jira_scraper.JIRAScraperEvent(
          10, {'project': 5}, uuid=event.uuid, timestamp=event.timestamp)
        self.assertEqual(event, expected_event)

    def testGetIncidentIssuesCount(self, mock_bus, mock_sandstorm, mock_jira):
        mock_jira_obj = mock_jira.return_value
        mock_result_list = mock.create_autospec(
          jira.client.ResultList, instance=True, total=10)
        mock_jira_obj.search_issues.return_value = mock_result_list

        result = jira_scraper.GetIncidentIssuesCount(mock_jira_obj)

        self.assertEqual(result, 10)
        mock_jira_obj.search_issues.assert_called_once_with(
          jira_scraper.INCIDENT_JQL, maxResults=0)

    @staticmethod
    def makeMockIssue(project_name):
        issue = mock.create_autospec(jira.resources.Issue, instance=True)
        issue.fields = mock.Mock()
        issue.fields.project = mock.create_autospec(
          jira.resources.Project, instance=True)
        issue.fields.project.name = project_name
        return issue

    def testGetProductionBugsCountByProject(self, mock_bus, mock_sandstorm,
                                            mock_jira):
        issues = iter([
          self.makeMockIssue('projectA'),
          self.makeMockIssue('projectB'),
          self.makeMockIssue('projectA'),
          self.makeMockIssue('projectB'),
          self.makeMockIssue('projectA'),
        ])

        mock_jira_obj = mock_jira.return_value
        mock_jira_obj.search_issues.side_effect = [
          mock.create_autospec(
            jira.client.ResultList, total=5, __iter__=mock.Mock(
              return_value=itertools.islice(issues, 2))),
          mock.create_autospec(
            jira.client.ResultList, total=5, __iter__=mock.Mock(
              return_value=itertools.islice(issues, 2))),
          mock.create_autospec(
            jira.client.ResultList, total=5, __iter__=mock.Mock(
              return_value=itertools.islice(issues, 2))),
        ]

        result = jira_scraper.GetProductionBugsCountByProject(mock_jira_obj,
                                                              batch_size=2)

        self.assertEqual(result, {'projectA': 3, 'projectB': 2})
        mock_jira_obj.search_issues.assert_has_calls([
          mock.call(jira_scraper.PRODUCTION_BUGS_JQL,
                    startAt=0, maxResults=2, fields='project'),
          mock.call(jira_scraper.PRODUCTION_BUGS_JQL,
                    startAt=2, maxResults=2, fields='project'),
          mock.call(jira_scraper.PRODUCTION_BUGS_JQL,
                    startAt=4, maxResults=2, fields='project'),
        ])


if __name__ == '__main__':
    unittest.main()
