#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Simple script that queries GitHub for all open PRs, then finds the ones without
issue number in title, and the ones where the linked JIRA is already closed
"""

import os
import sys
sys.path.append(os.path.dirname(__file__))
import argparse
import json
import re
from github import Github
from jira import JIRA
from datetime import datetime
from time import strftime
try:
  from jinja2 import Environment, BaseLoader
  can_do_html = True
except:
  can_do_html = False

def read_config():
  parser = argparse.ArgumentParser(description='Find open Pull Requests that need attention')
  parser.add_argument('--json', action='store_true', default=False, help='Output as json')
  parser.add_argument('--html', action='store_true', default=False, help='Output as html')
  parser.add_argument('--token', help='Github access token in case you query too often anonymously')
  newconf = parser.parse_args()
  return newconf


def out(text):
  global conf
  if not (conf.json or conf.html):
    print(text)

def make_html(dict):
  if not can_do_html:
    print ("ERROR: Cannot generate HTML. Please install jinja2")
    sys.exit(1)
  global conf
  template = Environment(loader=BaseLoader).from_string("""
  <h1>Solr Github PR report</h1>

  <p>Number of open Pull Requests: {{ open_count }}</p>

  <h2>PRs lacking JIRA reference in title ({{ no_jira_count }})</h2>
  <ul>
  {% for pr in no_jira %}
    <li><a href="https://github.com/apache/solr/pull/{{ pr.number }}">#{{ pr.number }}: {{ pr.created }} {{ pr.title }}</a> ({{ pr.user }})</li>
  {%- endfor %}
  </ul>

  <h2>Open PRs with a resolved JIRA ({{ closed_jira_count }})</h2>
  <ul>
  {% for pr in closed_jira %}
    <li><a href="https://github.com/apache/solr/pull/{{ pr.pr_number }}">#{{ pr.pr_number }}</a>: <a href="https://issues.apache.org/jira/browse/{{ pr.issue_key }}">{{ pr.status }} {{ pr.resolution_date }} {{ pr.issue_key}}: {{ pr.issue_summary }}</a> ({{ pr.assignee }})</li>
  {%- endfor %}
  </ul>
  """)
  return template.render(dict)

def main():
  global conf
  conf = read_config()
  token = conf.token if conf.token is not None else None
  if token:
    gh = Github(token)
  else:
    gh = Github()
  jira = JIRA('https://issues.apache.org/jira')
  result = {}
  repo = gh.get_repo('apache/solr')
  open_prs = repo.get_pulls(state='open')
  out("Solr Github PR report")
  out("============================")
  out("Number of open Pull Requests: %s" % open_prs.totalCount)
  result['open_count'] = open_prs.totalCount
  active_prs = list(filter(lambda x: not x.draft and not x.user.login == 'solrbot', open_prs))
  out("Number of active non-draft, non-solrbot Pull Requests: %s" % len(active_prs))

  lack_jira = list(filter(lambda x: not re.match(r'.*\b(SOLR)-\d{3,6}\b', x.title), active_prs))
  result['no_jira_count'] = len(lack_jira)
  lack_jira_list = []
  for pr in lack_jira:
    lack_jira_list.append({'title': pr.title, 'number': pr.number, 'user': pr.user.login, 'created': pr.created_at.strftime("%Y-%m-%d")})
  result['no_jira'] = lack_jira_list
  out("\nActive PRs lacking JIRA reference in title")
  for pr in lack_jira_list:
    out("  #%s: %s %s (%s)" % (pr['number'], pr['created'], pr['title'], pr['user'] ))

  out("\nOpen PRs with a resolved JIRA")
  has_jira = list(filter(lambda x: re.match(r'.*\b(SOLR)-\d{3,6}\b', x.title), open_prs))

  issue_ids = []
  issue_to_pr = {}
  for pr in has_jira:
    jira_issue_str = re.match(r'.*\b((SOLR)-\d{3,6})\b', pr.title).group(1)
    issue_ids.append(jira_issue_str)
    issue_to_pr[jira_issue_str] = pr

  resolved_jiras = jira.search_issues(jql_str="key in (%s) AND status in ('Closed', 'Resolved')" % ", ".join(issue_ids))
  closed_jiras = []
  for issue in resolved_jiras:
    pr_title = issue_to_pr[issue.key].title
    pr_number = issue_to_pr[issue.key].number
    assignee = issue.fields.assignee.name if issue.fields.assignee else None
    closed_jiras.append({ 'issue_key': issue.key,
                           'status': issue.fields.status.name,
                           'resolution': issue.fields.resolution.name,
                           'resolution_date': issue.fields.resolutiondate[:10],
                           'pr_number': pr_number,
                           'pr_title': pr_title,
                           'issue_summary': issue.fields.summary,
                           'assignee': assignee})

  closed_jiras.sort(key=lambda r: r['pr_number'], reverse=True)
  for issue in closed_jiras:
    out("  #%s: %s %s %s: %s (%s)" % (issue['pr_number'],
                                  issue['status'],
                                  issue['resolution_date'],
                                  issue['issue_key'],
                                  issue['issue_summary'],
                                  issue['assignee'])
        )
  result['closed_jira_count'] = len(resolved_jiras)
  result['closed_jira'] = closed_jiras

  if conf.json:
    print(json.dumps(result, indent=4))

  if conf.html:
    print(make_html(result))

if __name__ == '__main__':
  try:
    main()
  except KeyboardInterrupt:
    print('\nReceived Ctrl-C, exiting early')
