#!/usr/bin/python3
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

"""Create (or find) the Bugzilla bug for a new Nightly development cycle.

If a bug with the expected summary already exists, its ID is reused so
that retries don't produce duplicates.

Usage:
    BUGZILLA_API_KEY=<key> python3 create-nightly-bug.py <VERSION>

Set --staging to use bugzilla-dev.allizom.org for testing.
The bug ID is printed to stdout; status messages go to stderr.
"""

import json
import os
import sys
import urllib.error
import urllib.parse
import urllib.request

BUGZILLA_PROD_URL = "https://bugzilla.mozilla.org/rest/bug"
BUGZILLA_STAGING_URL = "https://bugzilla-dev.allizom.org/rest/bug"
PRODUCT = "Firefox for Android"
COMPONENT = "General"
SUMMARY_TEMPLATE = "Start the nightly {} development cycle"
RELEASE_CHECKLIST_URL = (
    "https://firefox-source-docs.mozilla.org/mobile/android/fenix/"
    "release-checklist.html"
    "#dev-team-starting-the-next-nightly-development-cycle"
)


def _bugzilla_request(url, data=None, api_key=None):
    if api_key:
        sep = "&" if "?" in url else "?"
        url = f"{url}{sep}api_key={api_key}"
    req = urllib.request.Request(
        url,
        data=data,
        headers={"Content-Type": "application/json"} if data else {},
    )
    try:
        with urllib.request.urlopen(req) as resp:
            return json.loads(resp.read())
    except urllib.error.HTTPError as e:
        body = e.read().decode("utf-8", errors="replace")
        print(f"ERROR: Bugzilla API returned {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


def find_existing_bug(base_url, version, api_key):
    params = urllib.parse.urlencode({
        "product": PRODUCT,
        "component": COMPONENT,
        "summary": SUMMARY_TEMPLATE.format(version),
    })
    result = _bugzilla_request(f"{base_url}?{params}", api_key=api_key)
    expected = SUMMARY_TEMPLATE.format(version)
    for bug in result.get("bugs", []):
        if bug["summary"] == expected:
            return bug["id"]
    return None


def create_bug(base_url, version, api_key):
    summary = SUMMARY_TEMPLATE.format(version)
    description = (
        "Follow **[[Dev team] Starting the next Nightly development cycle]"
        f"({RELEASE_CHECKLIST_URL})**"
    )
    payload = json.dumps({
        "product": PRODUCT,
        "component": COMPONENT,
        "summary": summary,
        "description": description,
        "type": "task",
        "version": "unspecified",
        "op_sys": "Android",
        "platform": "All",
    }).encode("utf-8")
    result = _bugzilla_request(base_url, data=payload, api_key=api_key)
    return result["id"]


def main():
    args = sys.argv[1:]
    staging = "--staging" in args
    if staging:
        args.remove("--staging")

    if len(args) != 1 or not args[0].isdigit():
        print("Usage: create-nightly-bug.py [--staging] VERSION", file=sys.stderr)
        print("Example: create-nightly-bug.py 150", file=sys.stderr)
        print("         create-nightly-bug.py --staging 150", file=sys.stderr)
        print("", file=sys.stderr)
        print("Requires BUGZILLA_API_KEY environment variable.", file=sys.stderr)
        sys.exit(1)

    version = args[0]
    base_url = BUGZILLA_STAGING_URL if staging else BUGZILLA_PROD_URL
    api_key = os.environ.get("BUGZILLA_API_KEY")
    if not api_key:
        print(
            "ERROR: BUGZILLA_API_KEY environment variable is not set.",
            file=sys.stderr,
        )
        sys.exit(1)

    if staging:
        print("Using staging instance (bugzilla-dev.allizom.org).", file=sys.stderr)

    existing = find_existing_bug(base_url, version, api_key)
    if existing:
        print(
            f"Bug {existing} already exists for nightly {version}.",
            file=sys.stderr,
        )
        print(existing)
        return

    bug_id = create_bug(base_url, version, api_key)
    print(f"Created bug {bug_id} for nightly {version}.", file=sys.stderr)
    print(bug_id)


if __name__ == "__main__":
    main()
