#!/usr/bin/python3
import argparse
import logging
import sys
from urllib.parse import urljoin, urlencode
from collections import defaultdict
import yaml
import requests

log = logging.getLogger("redmine-remind")

DEFAULT_REDMINE_URL = "https://redmine.tails.boum.org/code/"
DEFAULT_QUERY_IDS = "316,317"


class Fail(Exception):
    pass


class Redmine:
    def __init__(self, server, api_key):
        self.server = server
        self.api_key = api_key

    def query(self, api, **kw):
        url = urljoin(self.server, api)
        if kw:
            url += "?" + urlencode(kw)
        log.info("Querying %s", url)
        res = requests.get(url, headers={
            "X-Redmine-API-Key": self.api_key
        })
        res.raise_for_status()
        return res.json()

    def whoami(self):
        return self.query("users/current.json")

    def get_user(self, user_id):
        return self.query(f"users/{user_id}.json")


def main():
    parser = argparse.ArgumentParser(description="Fetch reminder information from open redmine issyes")
    parser.add_argument("--verbose", "-v", action="store_true", help="verbose output")
    parser.add_argument("--debug", action="store_true", help="debug output")
    parser.add_argument("--api-key", action="store", required=True,
                        help="Redmine API key; use @file to read it from a file (required)")
    parser.add_argument("--server", action="store", default=DEFAULT_REDMINE_URL,
                        help="Redmine URL. Default: " + DEFAULT_REDMINE_URL)
    parser.add_argument("--query-ids", action="store", default=DEFAULT_QUERY_IDS,
                        help="IDs of queries to run. Default: " + DEFAULT_QUERY_IDS)

    args = parser.parse_args()

    log_format = "%(levelname)s %(message)s"
    level = logging.WARN
    if args.debug:
        level = logging.DEBUG
    elif args.verbose:
        level = logging.INFO
    logging.basicConfig(level=level, stream=sys.stderr, format=log_format)

    # Read API key
    api_key = args.api_key
    if api_key.startswith("@"):
        with open(api_key[1:], "rt") as fd:
            api_key = fd.read().strip()

    query_ids = args.query_ids.split(",")

    # Fetch issues
    redmine = Redmine(args.server, api_key)
    issues_by_name = defaultdict(list)
    emails_by_name = {}
    for query_id in query_ids:
        res = redmine.query("issues.json", query_id=query_id, project_id="tails")
        for issue in res["issues"]:
            assigned_to = issue.get("assigned_to")
            if assigned_to is None:
                continue
            if assigned_to["name"] not in emails_by_name:
                # Fetch email addresses for users
                user = redmine.get_user(assigned_to["id"])
                emails_by_name[assigned_to["name"]] = user.get("mail")

            issues_by_name[assigned_to["name"]].append(
                    {k: v for k, v in issue.items() if k in ("id", "updated_on", "created_on", "subject")})

    # Build the output structure
    res = {}
    for name, ids in issues_by_name.items():
        data = {
            "issues": ids,
        }
        email = emails_by_name.get(name)
        if email is not None:
            data["email"] = email
        res[name] = data

    # Output the results
    yaml.dump(res, sys.stdout, default_flow_style=False)


if __name__ == "__main__":
    try:
        main()
    except Fail as e:
        print(e, file=sys.stderr)
        sys.exit(1)
    except Exception:
        log.exception("uncaught exception")
