#!/usr/bin/env python3

# Copyright (c) 2022 Intel Corp.
# SPDX-License-Identifier: Apache-2.0

import argparse
import datetime
import os
import sys
import time
from collections import defaultdict

from github import Auth, Github, GithubException
from github.GithubException import UnknownObjectException
from west.manifest import Manifest, ManifestProject

TOP_DIR = os.path.join(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(TOP_DIR, "scripts"))
from get_maintainer import Maintainers  # noqa: E402

zephyr_base = os.getenv('ZEPHYR_BASE', os.path.join(TOP_DIR, '..'))


def log(s):
    if args.verbose > 0:
        print(s, file=sys.stdout)


def parse_args():
    global args
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        allow_abbrev=False,
    )

    parser.add_argument(
        "-M",
        "--maintainer-file",
        required=False,
        default="MAINTAINERS.yml",
        help="Maintainer file to be used.",
    )

    group = parser.add_mutually_exclusive_group()
    group.add_argument(
        "-P",
        "--pull_request",
        required=False,
        default=None,
        type=int,
        help="Operate on one pull-request only.",
    )
    group.add_argument(
        "-I", "--issue", required=False, default=None, type=int, help="Operate on one issue only."
    )
    group.add_argument("-s", "--since", required=False, help="Process pull-requests since date.")
    group.add_argument(
        "-m", "--modules", action="store_true", help="Process pull-requests from modules."
    )

    parser.add_argument("-y", "--dry-run", action="store_true", default=False, help="Dry run only.")

    parser.add_argument("-o", "--org", default="zephyrproject-rtos", help="Github organisation")

    parser.add_argument("-r", "--repo", default="zephyr", help="Github repository")

    parser.add_argument(
        "--updated-manifest",
        default=None,
        help="Updated manifest file to compare against current west.yml",
    )

    parser.add_argument("-v", "--verbose", action="count", default=0, help="Verbose Output")

    args = parser.parse_args()


def process_manifest(old_manifest_file):
    log("Processing manifest changes")
    if not os.path.isfile("west.yml") or not os.path.isfile(old_manifest_file):
        log("No west.yml found, skipping...")
        return []
    old_manifest = Manifest.from_file(old_manifest_file)
    new_manifest = Manifest.from_file("west.yml")
    old_projs = set((p.name, p.revision) for p in old_manifest.projects)
    new_projs = set((p.name, p.revision) for p in new_manifest.projects)
    # Removed projects
    rprojs = set(filter(lambda p: p[0] not in list(p[0] for p in new_projs), old_projs - new_projs))
    # Updated projects
    uprojs = set(filter(lambda p: p[0] in list(p[0] for p in old_projs), new_projs - old_projs))
    # Added projects
    aprojs = new_projs - old_projs - uprojs

    # All projs
    projs = rprojs | uprojs | aprojs
    projs_names = [name for name, rev in projs]

    log(f"found modified projects: {projs_names}")
    areas = []
    for p in projs_names:
        areas.append(f'West project: {p}')

    log(f'manifest areas: {areas}')
    return areas


def process_pr(gh, maintainer_file, number):
    gh_repo = gh.get_repo(f"{args.org}/{args.repo}")
    pr = gh_repo.get_pull(number)

    log(f"working on https://github.com/{args.org}/{args.repo}/pull/{pr.number} : {pr.title}")

    labels = set()
    area_counter = defaultdict(int)
    found_maintainers = defaultdict(int)

    num_files = 0
    fn = list(pr.get_files())

    if pr.commits == 1 and (pr.additions <= 1 and pr.deletions <= 1):
        labels = {'size: XS'}

    if len(fn) > 500:
        log(f"Too many files changed ({len(fn)}), skipping....")
        return

    # areas where assignment happens if only said areas are affected
    meta_areas = ['Release Notes', 'Documentation', 'Samples', 'Tests']

    for changed_file in fn:
        num_files += 1
        log(f"file: {changed_file.filename}")

        areas = []
        if changed_file.filename in ['west.yml', 'submanifests/optional.yaml']:
            if not args.updated_manifest:
                log("No updated manifest, cannot process west.yml changes, skipping...")
                continue
            parsed_areas = process_manifest(old_manifest_file=args.updated_manifest)
            for _area in parsed_areas:
                area_match = maintainer_file.name2areas(_area)
                if area_match:
                    areas.extend(area_match)
        else:
            areas = maintainer_file.path2areas(changed_file.filename)

        log(f"areas for {changed_file}: {areas}")

        if not areas:
            continue

        # instance of an area, for example a driver or a board, not APIs or subsys code.
        is_instance = False
        sorted_areas = sorted(areas, key=lambda x: 'Platform' in x.name, reverse=True)
        for area in sorted_areas:
            # do not count cmake file changes, i.e. when there are changes to
            # instances of an area listed in both the subsystem and the
            # platform implementing it
            if 'CMakeLists.txt' in changed_file.filename or area.name in meta_areas:
                c = 0
            else:
                c = 1 if not is_instance else 0

            area_counter[area] += c
            log(f"area counter: {area_counter}")
            labels.update(area.labels)
            # FIXME: Here we count the same file multiple times if it exists in
            # multiple areas with same maintainer
            for area_maintainer in area.maintainers:
                found_maintainers[area_maintainer] += c

            if 'Platform' in area.name:
                is_instance = True

    area_counter = dict(sorted(area_counter.items(), key=lambda item: item[1], reverse=True))
    log(f"Area matches: {area_counter}")
    log(f"labels: {labels}")

    # Create a list of collaborators ordered by the area match
    collab = list()
    for area in area_counter:
        collab += maintainer_file.areas[area.name].maintainers
        collab += maintainer_file.areas[area.name].collaborators
    collab = list(dict.fromkeys(collab))
    log(f"collab: {collab}")

    _all_maintainers = dict(
        sorted(found_maintainers.items(), key=lambda item: item[1], reverse=True)
    )

    log(f"Submitted by: {pr.user.login}")
    log(f"candidate maintainers: {_all_maintainers}")

    ranked_assignees = []
    assignees = None

    # we start with areas with most files changed and pick the maintainer from the first one.
    # if the first area is an implementation, i.e. driver or platform, we
    # continue searching for any other areas involved
    for area, count in area_counter.items():
        # if only meta area is affected, assign one of the maintainers of that area
        if area.name in meta_areas and len(area_counter) == 1:
            assignees = area.maintainers
            break
        # if no maintainers, skip
        if count == 0 or len(area.maintainers) == 0:
            continue
        # if there are maintainers, but no assignees yet, set them
        if len(area.maintainers) > 0:
            if pr.user.login in area.maintainers:
                # If submitter = assignee, try to pick next area and assign
                # someone else other than the submitter, otherwise when there
                # are other maintainers for the area, assign them.
                if len(area.maintainers) > 1:
                    assignees = area.maintainers.copy()
                    assignees.remove(pr.user.login)
                else:
                    continue
            else:
                assignees = area.maintainers

        # found a non-platform area that was changed, pick assignee from this
        # area and put them on top of the list, otherwise just append.
        if 'Platform' not in area.name:
            ranked_assignees.insert(0, area.maintainers)
            break
        else:
            ranked_assignees.append(area.maintainers)

    if ranked_assignees:
        assignees = ranked_assignees[0]

    if assignees:
        prop = (found_maintainers[assignees[0]] / num_files) * 100
        log(f"Picked assignees: {assignees} ({prop:.2f}% ownership)")
        log("+++++++++++++++++++++++++")
    elif len(_all_maintainers) > 0:
        # if we have maintainers found, but could not pick one based on area,
        # then pick the one with most changes
        assignees = [next(iter(_all_maintainers))]

    # Set labels
    if labels:
        if len(labels) < 10:
            for label in labels:
                log(f"adding label {label}...")
                if not args.dry_run:
                    pr.add_to_labels(label)
        else:
            log("Too many labels to be applied")

    if collab:
        reviewers = []
        existing_reviewers = set()

        revs = pr.get_reviews()
        for review in revs:
            existing_reviewers.add(review.user)

        rl = pr.get_review_requests()
        for page, r in enumerate(rl):
            existing_reviewers |= set(r.get_page(page))

        # check for reviewers that remove themselves from list of reviewer and
        # do not attempt to add them again based on MAINTAINERS file.
        self_removal = []
        for event in pr.get_issue_events():
            if event.event == 'review_request_removed' and event.actor == event.requested_reviewer:
                self_removal.append(event.actor)

        for collaborator in collab:
            try:
                gh_user = gh.get_user(collaborator)
                if pr.user == gh_user or gh_user in existing_reviewers:
                    continue
                if not gh_repo.has_in_collaborators(gh_user):
                    log(f"Skip '{collaborator}': not in collaborators")
                    continue
                if gh_user in self_removal:
                    log(f"Skip '{collaborator}': self removed")
                    continue
                reviewers.append(collaborator)
            except UnknownObjectException as e:
                log(f"Can't get user '{collaborator}', account does not exist anymore? ({e})")

        if len(existing_reviewers) < 15:
            reviewer_vacancy = 15 - len(existing_reviewers)
            reviewers = reviewers[:reviewer_vacancy]
        else:
            log(
                "not adding reviewers because the existing reviewer count is greater than or "
                "equal to 15. Adding maintainers of all areas as reviewers instead."
            )
            # FIXME: Here we could also add collaborators of the areas most
            # affected, i.e. the one with the final assigne.
            reviewers = list(_all_maintainers.keys())

        if reviewers:
            try:
                log(f"adding reviewers {reviewers}...")
                if not args.dry_run:
                    pr.create_review_request(reviewers=reviewers)
            except GithubException:
                log("can't add reviewer")

    ms = []
    # assignees
    if assignees and (not pr.assignee or args.dry_run):
        try:
            for assignee in assignees:
                u = gh.get_user(assignee)
                ms.append(u)
        except GithubException:
            log("Error: Unknown user")

        for mm in ms:
            log(f"Adding assignee {mm}...")
            if not args.dry_run:
                pr.add_to_assignees(mm)
    else:
        log("not setting assignee")

    time.sleep(1)


def process_issue(gh, maintainer_file, number):
    gh_repo = gh.get_repo(f"{args.org}/{args.repo}")
    issue = gh_repo.get_issue(number)

    log(f"Working on {issue.url}: {issue.title}")

    if issue.assignees:
        print(f"Already assigned {issue.assignees}, bailing out")
        return

    label_to_maintainer = defaultdict(set)
    for _, area in maintainer_file.areas.items():
        if not area.labels:
            continue

        labels = set()
        for label in area.labels:
            labels.add(label.lower())
        labels = tuple(sorted(labels))

        for maintainer in area.maintainers:
            label_to_maintainer[labels].add(maintainer)

    # Add extra entries for areas with multiple labels so they match with just
    # one label if it's specific enough.
    for areas, maintainers in dict(label_to_maintainer).items():
        for area in areas:
            if tuple([area]) not in label_to_maintainer:
                label_to_maintainer[tuple([area])] = maintainers

    issue_labels = set()
    for label in issue.labels:
        label_name = label.name.lower()
        if tuple([label_name]) not in label_to_maintainer:
            print(f"Ignoring label: {label}")
            continue
        issue_labels.add(label_name)
    issue_labels = tuple(sorted(issue_labels))

    print(f"Using labels: {issue_labels}")

    if issue_labels not in label_to_maintainer:
        print("no match for the label set, not assigning")
        return

    for maintainer in label_to_maintainer[issue_labels]:
        log(f"Adding {maintainer} to {issue.html_url}")
        if not args.dry_run:
            issue.add_to_assignees(maintainer)


def process_modules(gh, maintainers_file):
    manifest = Manifest.from_file()

    repos = {}
    for project in manifest.get_projects([]):
        if not manifest.is_active(project):
            continue

        if isinstance(project, ManifestProject):
            continue

        area = f"West project: {project.name}"
        if area not in maintainers_file.areas:
            log(f"No area for: {area}")
            continue

        maintainers = maintainers_file.areas[area].maintainers
        if not maintainers:
            log(f"No maintainers for: {area}")
            continue

        collaborators = maintainers_file.areas[area].collaborators

        log(f"Found {area}, maintainers={maintainers}, collaborators={collaborators}")

        repo_name = f"{args.org}/{project.name}"
        repos[repo_name] = maintainers_file.areas[area]

    query = "is:open is:pr no:assignee"
    if repos:
        query += ' ' + ' '.join(f"repo:{repo}" for repo in repos)

    issues = gh.search_issues(query=query)
    for issue in issues:
        pull = issue.as_pull_request()

        if pull.draft:
            continue

        if pull.assignees:
            log(f"ERROR: {pull.html_url} should have no assignees, found {pull.assignees}")
            continue

        repo_name = f"{args.org}/{issue.repository.name}"
        area = repos[repo_name]

        for maintainer in area.maintainers:
            log(f"Assigning {maintainer} to {pull.html_url}")
            if not args.dry_run:
                pull.add_to_assignees(maintainer)
                pull.create_review_request(maintainer)

        for collaborator in area.collaborators:
            log(f"Adding {collaborator} to {pull.html_url}")
            if not args.dry_run:
                pull.create_review_request(collaborator)


def main():
    parse_args()

    token = os.environ.get('GITHUB_TOKEN', None)
    if not token:
        sys.exit(
            'Github token not set in environment, please set the '
            'GITHUB_TOKEN environment variable and retry.'
        )

    gh = Github(auth=Auth.Token(token))
    maintainer_file = Maintainers(args.maintainer_file)

    if args.pull_request:
        process_pr(gh, maintainer_file, args.pull_request)
    elif args.issue:
        process_issue(gh, maintainer_file, args.issue)
    elif args.modules:
        process_modules(gh, maintainer_file)
    else:
        if args.since:
            since = args.since
        else:
            today = datetime.date.today()
            since = today - datetime.timedelta(days=1)

        common_prs = (
            f'repo:{args.org}/{args.repo} is:open is:pr base:main '
            f'-is:draft no:assignee created:>{since}'
        )
        pulls = gh.search_issues(query=f'{common_prs}')

        for issue in pulls:
            process_pr(gh, maintainer_file, issue.number)


if __name__ == "__main__":
    main()
