# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd

"""Handlers to process alert notification messages."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import itertools
import logging
import rfc822

import settings
from businesslogic import work_env
from features import commitlogcommands
from framework import framework_constants
from framework import monorailcontext
from framework import emailfmt
from tracker import tracker_constants
from tracker import tracker_helpers

AlertEmailHeader = emailfmt.AlertEmailHeader


def IsAllowlisted(email_addr):
  """Returns whether a given email is from one of the allowlisted domains."""
  return email_addr.endswith(settings.alert_allowlisted_suffixes)


def IsCommentSizeReasonable(comment):
  # type: str -> bool
  """Returns whether a given comment string is a reasonable size."""
  return len(comment) <= tracker_constants.MAX_COMMENT_CHARS


def FindAlertIssue(services, cnxn, project_id, incident_label):
  """Find the existing issue with the incident_label."""
  if not incident_label:
    return None

  label_id = services.config.LookupLabelID(
      cnxn, project_id, incident_label)
  if not label_id:
    return None

  # If a new notification is sent with an existing incident ID, then it
  # should be added as a new comment into the existing issue.
  #
  # If there are more than one issues with a given incident ID, then
  # it's either
  # - there is a bug in this module,
  # - the issues were manually updated with the same incident ID, OR
  # - an issue auto update program updated the issues with the same
  #  incident ID, which also sounds like a bug.
  #
  # In any cases, the latest issue should be used, whichever status it has.
  # - The issue of an ongoing incident can be mistakenly closed by
  # engineers.
  # - A closed incident can be reopened, and, therefore, the issue also
  # needs to be re-opened.
  issue_ids = services.issue.GetIIDsByLabelIDs(
      cnxn, [label_id], project_id, None)
  issues = services.issue.GetIssues(cnxn, issue_ids)
  if issues:
    return max(issues, key=lambda issue: issue.modified_timestamp)
  return None


def GetAlertProperties(services, cnxn, project_id, incident_id, trooper_queue,
                       msg):
  """Create a dict of issue property values for the alert to be created with.

  Args:
    cnxn: connection to SQL database.
    project_id: the ID of the Monorail project, in which the alert should
      be created in.
    incident_id: string containing an optional unique incident used to
      de-dupe alert issues.
    trooper_queue: the label specifying the trooper queue to add an issue into.
    msg: the email.Message object containing the alert notification.

  Returns:
    A dict of issue property values to be used for issue creation.
  """
  proj_config = services.config.GetProjectConfig(cnxn, project_id)
  user_svc = services.user
  known_labels = set(wkl.label.lower() for wkl in proj_config.well_known_labels)

  props = dict(
      owner_id=_GetOwnerID(user_svc, cnxn, msg.get(AlertEmailHeader.OWNER)),
      cc_ids=_GetCCIDs(user_svc, cnxn, msg.get(AlertEmailHeader.CC)),
      component_ids=_GetComponentIDs(
          proj_config, msg.get(AlertEmailHeader.COMPONENT)),

      # Props that are added as labels.
      trooper_queue=(trooper_queue or 'Infra-Troopers-Alerts'),
      incident_label=_GetIncidentLabel(incident_id),
      priority=_GetPriority(known_labels, msg.get(AlertEmailHeader.PRIORITY)),
      oses=_GetOSes(known_labels, msg.get(AlertEmailHeader.OS)),
      issue_type=_GetIssueType(known_labels, msg.get(AlertEmailHeader.TYPE)),

      field_values=[],
  )

  # Props that depend on other props.
  props.update(
      status=_GetStatus(proj_config, props['owner_id'],
                        msg.get(AlertEmailHeader.STATUS)),
      labels=_GetLabels(msg.get(AlertEmailHeader.LABEL),
                        props['trooper_queue'], props['incident_label'],
                        props['priority'], props['issue_type'], props['oses']),
  )

  return props


def ProcessEmailNotification(
    services, cnxn, project, project_addr, from_addr, auth, subject, body,
    incident_id, msg, trooper_queue=None):
  # type: (...) -> None
  """Process an alert notification email to create or update issues.""

  Args:
    cnxn: connection to SQL database.
    project: Project PB for the project containing the issue.
    project_addr: string email address the alert email was sent to.
    from_addr: string email address of the user who sent the alert email
        to our server.
    auth: AuthData object with user_id and email address of the user who
        will file the alert issue.
    subject: the subject of the email message
    body: the body text of the email message
    incident_id: string containing an optional unique incident used to
        de-dupe alert issues.
    msg: the email.Message object that the notification was delivered via.
    trooper_queue: the label specifying the trooper queue that the alert
      notification was sent to. If not given, the notification is sent to
      Infra-Troopers-Alerts.

  Side-effect:
    Creates an issue or issue comment, if no error was reported.
  """
  # Make sure the email address is allowlisted.
  if not IsAllowlisted(from_addr):
    logging.info('Unauthorized %s tried to send alert to %s',
                 from_addr, project_addr)
    return

  formatted_body = 'Filed by %s on behalf of %s\n\n%s' % (
      auth.email, from_addr, body)
  if not IsCommentSizeReasonable(formatted_body):
    logging.info(
        '%s tried to send an alert comment that is too long in %s', from_addr,
        project_addr)
    return

  mc = monorailcontext.MonorailContext(services, auth=auth, cnxn=cnxn)
  mc.LookupLoggedInUserPerms(project)
  with work_env.WorkEnv(mc, services) as we:
    alert_props = GetAlertProperties(
        services, cnxn, project.project_id, incident_id, trooper_queue, msg)
    alert_issue = FindAlertIssue(
        services, cnxn, project.project_id, alert_props['incident_label'])

    if alert_issue:
      # Add a reply to the existing issue for this incident.
      services.issue.CreateIssueComment(
          cnxn, alert_issue, auth.user_id, formatted_body)
    else:
      # Create a new issue for this incident. To preserve previous behavior do
      # not raise filter rule errors.
      alert_issue, _ = we.CreateIssue(
          project.project_id,
          subject,
          alert_props['status'],
          alert_props['owner_id'],
          alert_props['cc_ids'],
          alert_props['labels'],
          alert_props['field_values'],
          alert_props['component_ids'],
          formatted_body,
          raise_filter_errors=False)

    # Update issue using commands.
    lines = body.strip().split('\n')
    uia = commitlogcommands.UpdateIssueAction(alert_issue.local_id)
    commands_found = uia.Parse(
        cnxn, project.project_name, auth.user_id, lines,
        services, strip_quoted_lines=True)

    if commands_found:
      uia.Run(mc, services)


def _GetComponentIDs(proj_config, components):
  comps = ['Infra']
  if components:
    components = components.strip()
  if components:
    comps = [c.strip() for c in components.split(',')]
  return tracker_helpers.LookupComponentIDs(comps, proj_config)


def _GetIncidentLabel(incident_id):
  return 'Incident-Id-%s'.strip().lower() % incident_id if incident_id else ''


def _GetLabels(custom_labels, trooper_queue, incident_label, priority,
               issue_type, oses):
  labels = set(['Restrict-View-Google'.lower()])
  labels.update(
      # Whitespaces in a label can cause UI rendering each of the words as
      # a separate label.
      ''.join(label.split()).lower() for label in itertools.chain(
          custom_labels.split(',') if custom_labels else [],
          [trooper_queue, incident_label, priority, issue_type],
          oses)
      if label
  )
  return list(labels)


def _GetOwnerID(user_svc, cnxn, owner_email):
  if owner_email:
    owner_email = owner_email.strip()
  if not owner_email:
    return framework_constants.NO_USER_SPECIFIED
  emails = [addr for _, addr in rfc822.AddressList(owner_email)]
  return user_svc.LookupExistingUserIDs(
      cnxn, emails).get(owner_email) or framework_constants.NO_USER_SPECIFIED


def _GetCCIDs(user_svc, cnxn, cc_emails):
  if cc_emails:
    cc_emails = cc_emails.strip()
  if not cc_emails:
    return []
  emails = [addr for _, addr in rfc822.AddressList(cc_emails)]
  return [userID for _, userID
          in user_svc.LookupExistingUserIDs(cnxn, emails).iteritems()
          if userID is not None]


def _GetPriority(known_labels, priority):
  priority_label = ('Pri-%s' % priority).strip().lower()
  if priority:
    if priority_label in known_labels:
      return priority_label
    logging.info('invalid priority %s for alerts; default to pri-2', priority)

  # XXX: what if 'Pri-2' doesn't exist in known_labels?
  return 'pri-2'


def _GetStatus(proj_config, owner_id, status):
  # XXX: what if assigned and available are not in known_statuses?
  if status:
    status = status.strip().lower()
  if owner_id:
    # If there is an owner, the status must be 'Assigned'.
    if status and status != 'assigned':
      logging.info(
          'invalid status %s for an alert with an owner; default to assigned',
          status)
    return 'assigned'

  if status:
    if tracker_helpers.MeansOpenInProject(status, proj_config):
      return status
    logging.info('invalid status %s for an alert; default to available', status)

  return 'available'


def _GetOSes(known_labels, oses):
  if oses:
    oses = oses.strip().lower()
  if not oses:
    return []

  os_labels_to_lookup = {
      ('os-%s' % os).strip() for os in oses.split(',') if os
  }
  os_labels_to_return = os_labels_to_lookup & known_labels
  invalid_os_labels = os_labels_to_lookup - os_labels_to_return
  if invalid_os_labels:
    logging.info('invalid OSes %s', ','.join(invalid_os_labels))

  return list(os_labels_to_return)


def _GetIssueType(known_labels, issue_type):
  if issue_type:
    issue_type = issue_type.strip().lower()
  if issue_type is None:
    return None

  issue_type_label = 'type-%s' % issue_type
  if issue_type_label in known_labels:
    return issue_type_label

  logging.info('invalid type %s for an alert; default to None', issue_type)
  return None
