"""Lambda handler to query JIRA and publish JIRAScraperEvent Events to RPS."""

import collections
import logging
import sys

if 'code' in sys.modules:
    del sys.modules['code']
from code.justin.tv.dta.rockpaperscissors import environment
from code.justin.tv.dta.rockpaperscissors import event_bus
from code.justin.tv.dta.rockpaperscissors.proto.events import jira_scraper_pb2


INCIDENT_JQL = (
  'Project = INC AND resolution not in (Duplicate, Cancelled) AND'
  ' "Customer Impact" = Yes ORDER BY "Issue Start Time" DESC'
)
PRODUCTION_BUGS_JQL = (
  'project not in (Workplace, "IT Support", swag, "SWAG Projects") AND '
  'reporter in membersOf(Support) AND resolved is EMPTY ORDER BY created DESC'
)


logger = logging.getLogger()
logger.setLevel(logging.INFO)
logging.getLogger('boto3').setLevel(logging.WARNING)
logging.getLogger('botocore').setLevel(logging.WARNING)


def GetIncidentIssuesCount(jira_client):
    """Query JIRA for number of created incidents for all time.

    Args:
      jira_client: configured JIRA client object.

    Returns:
      integer
    """
    result_list = jira_client.search_issues(INCIDENT_JQL, maxResults=0)
    return result_list.total


def GetProductionBugsCountByProject(jira_client, batch_size=50):
    """Query JIRA for unresolved production bugs by project.

    Args:
      jira_client: configured JIRA client object.
      batch_size: integer, how many issues to request per query

    Returns:
      Dict with project names as keys and number of unresolved production
      bugs as values.
    """
    prod_bugs_by_project = collections.defaultdict(int)
    start_at = 0
    while True:
        issues = jira_client.search_issues(PRODUCTION_BUGS_JQL,
                                           startAt=start_at,
                                           maxResults=batch_size,
                                           fields='project')
        for issue in issues:
            prod_bugs_by_project[issue.fields.project.name] += 1
        start_at += batch_size
        if start_at >= issues.total:
            break
    return prod_bugs_by_project


def JIRAScraperEvent(total_incidents_issues, prod_bugs_by_project, uuid=None,
                     timestamp=None, attributes=None):
    """Make an Event of the JIRAScraperEvent type.

    Args:
      total_incidents_issues: integer, number of created incidents for all time
      prod_bugs_by_project: dict with project names as keys and number of
                            unresolved production bugs as values
      uuid: passed into event_bus.Event
      timestamp: passed into event_bus.Event
      attributes: passed into event_bus.Event

    Returns:
      event_bus.Event protobuf object.
    """
    jira_event_body = jira_scraper_pb2.JIRAScraperEvent()
    jira_event_body.total_incidents_issues = total_incidents_issues
    for project, total_production_bugs in prod_bugs_by_project.iteritems():
        entry = jira_event_body.production_bugs_per_project.add()
        entry.project = project
        entry.total_production_bugs = total_production_bugs
    return event_bus.Event(
      uuid=uuid,
      timestamp=timestamp,
      event_type='JIRAScraperEvent',
      body=jira_event_body.SerializeToString(),
      attributes=attributes)


def lambda_handler(event, context):
    env = environment.GetEnvironment(context)

    jira_client = env.JiraClient()
    e = JIRAScraperEvent(GetIncidentIssuesCount(jira_client),
                         GetProductionBugsCountByProject(jira_client))

    bus = env.EventBus()
    bus.PutEvent(e)
