# Copyright 2020 The Pigweed Authors
#
# Licensed 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
#
#     https://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.
"""Roll a project in an Android Repo Tool workspace."""

from __future__ import annotations

import collections
import dataclasses
import re
from typing import Generator, TYPE_CHECKING
import urllib
import xml.etree.ElementTree

import attrs
from PB.recipes.pigweed.repo_roller import InputProperties
from PB.recipe_modules.pigweed.checkout.options import (
    Options as CheckoutOptions,
)
from recipe_engine import config_types, recipe_test_api
from RECIPE_MODULES.pigweed.roll_util import api as roll_util_api

DEPS = [
    'fuchsia/auto_roller',
    'fuchsia/sso',
    'pigweed/checkout',
    'pigweed/roll_util',
    'recipe_engine/buildbucket',
    'recipe_engine/file',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/raw_io',
    'recipe_engine/step',
]

PROPERTIES = InputProperties


class _TreeBuilder(xml.etree.ElementTree.TreeBuilder):
    def comment(self, data):
        self.start(xml.etree.ElementTree.Comment, {})
        self.data(data)
        self.end(xml.etree.ElementTree.Comment)


def _is_branch(revision):
    """Return True if revision appears to be a branch name."""
    if re.search(r'^[0-9a-fA-F]{40}$', revision):
        return False
    return not revision.startswith('refs/tags/')


# ElementTree orders attributes differently in Python 2 and 3, but if given
# attributes in a specific order it preserves that order.
def _order_attributes(root):
    for el in root.iter():
        if len(el.attrib) > 1:
            new_attrib = sorted(el.attrib.items())
            el.attrib.clear()
            el.attrib.update(new_attrib)


@dataclasses.dataclass
class _RevisionChange:
    dir: config_types.Path
    old: str
    new: str
    direction: roll_util_api.Direction


def _update_project(api, checkout, path_to_update) -> _RevisionChange | None:
    new_revision = None

    # Try to get new_revision from the trigger.
    bb_remote = None
    commit = api.buildbucket.build.input.gitiles_commit
    if commit and commit.project:
        new_revision = commit.id
        host = commit.host
        bb_remote = f'https://{host}/{commit.project}'

    tree = _TreeBuilder()
    parser = xml.etree.ElementTree.XMLParser(target=tree)
    parser.feed(api.file.read_text('read manifest', checkout.manifest_path))
    parser.close()
    root = tree.close()

    defaults = {}
    for default in root.findall('default'):
        defaults.update(default.attrib)

    remotes = {}
    for rem in root.findall('remote'):
        remotes[rem.attrib['name']] = rem.attrib

    # Search for path_to_update and check the repository it refers to matches
    # the triggering repository. This check is mostly a config check and
    # shouldn't fail in real runs unless somebody moves around project
    # paths in the manifest without updating the builder definition.
    paths_found = []
    proj = None
    proj_attrib = {}

    for proj in root.findall('project'):
        # Sometimes projects don't define something in which case we need to
        # fall back on the remote specified by the project or the default for
        # the entire manifest.
        proj_attrib = {}
        proj_attrib.update(defaults)
        remote_name = proj.attrib.get('remote', defaults.get('remote', None))
        assert remote_name
        proj_attrib.update(remotes[remote_name])
        proj_attrib.update(proj.attrib)
        proj_attrib['fetch'] = api.sso.sso_to_https(proj_attrib['fetch'])

        # Apparently if path is left off name is used. This is mildly
        # infuriating, but easy to work around.
        if 'path' not in proj_attrib:
            proj_attrib['path'] = proj_attrib['name']

        paths_found.append(proj_attrib['path'])
        if proj_attrib['path'] == path_to_update:
            fetch_host = proj_attrib['fetch'].strip('/')
            if fetch_host.startswith('..'):
                fetch_host = urllib.parse.urljoin(
                    checkout.options.remote,
                    fetch_host,
                )

            manifest_remote = (
                fetch_host.rstrip('/') + '/' + proj_attrib['name'].strip('/')
            )
            if bb_remote and not checkout.remotes_equivalent(
                manifest_remote, bb_remote
            ):
                raise api.step.StepFailure(
                    "repo paths don't match: {} from manifest "
                    "and {} from buildbucket".format(manifest_remote, bb_remote)
                )
            break

        # Reset proj_attrib to None if this entry wasn't a match, so if this is
        # the last iteration the condition a few lines down will work.
        proj_attrib = {}

    if not proj_attrib:
        raise api.step.StepFailure(
            'cannot find "{}" in manifest (found {})'.format(
                path_to_update,
                ', '.join('"{}"'.format(x) for x in paths_found),
            )
        )

    if 'upstream' in proj_attrib:
        proj_branch = proj_attrib['upstream']
    elif 'revision' in proj_attrib and _is_branch(proj_attrib['revision']):
        proj_branch = proj_attrib['revision']
    else:
        proj_branch = 'main'

    # If we still don't have a revision then it wasn't in the trigger. (Perhaps
    # this was manually triggered.) In this case we need to determine the
    # latest revision of this repository. The use_trigger flag should have no
    # effect but using it to be explicit. Checking out even if not needed so
    # commit messages can be collected later.
    proj_dir = api.path.start_dir / 'project'
    proj_checkout = api.checkout(
        CheckoutOptions(
            remote=manifest_remote, branch=proj_branch, use_trigger=False
        ),
        root=proj_dir,
    )
    if new_revision is None:
        new_revision = api.checkout.get_revision(proj_dir)

    assert new_revision
    new_revision = str(new_revision)

    # If upstream not set we may be transitioning from tracking a branch to
    # rolling. In that case set upstream to be the revision, but only if the
    # revision appears to be a branch.
    if 'upstream' not in proj_attrib:
        if _is_branch(proj_attrib['revision']):
            # Explicitly update both proj.attrib and proj_attrib to minimize
            # confusion if these statements are moved around later.
            proj.attrib['upstream'] = proj_attrib['revision']
            proj_attrib['upstream'] = proj.attrib['upstream']
        else:
            raise api.step.StepFailure(
                'upstream not set and revision is not a branch, aborting'
            )

    old_revision = proj_attrib['revision']
    # Explicitly update both proj.attrib and proj_attrib to minimize confusion.
    proj_attrib['revision'] = proj.attrib['revision'] = new_revision

    direction = api.roll_util.Direction.FORWARD
    if not _is_branch(old_revision):
        direction = api.roll_util.get_roll_direction(
            proj_dir, old_revision, new_revision
        )

    if not api.roll_util.can_roll(direction):
        api.roll_util.skip_roll_step(
            manifest_remote, old_revision, new_revision
        )
        return

    _order_attributes(root)

    api.file.write_text(
        'write manifest',
        checkout.manifest_path,
        '<?xml version="1.0" encoding="UTF-8"?>\n{}\n'.format(
            xml.etree.ElementTree.tostring(root).decode(),
        ),
    )

    return _RevisionChange(
        dir=proj_dir,
        old=old_revision,
        new=new_revision,
        direction=direction,
    )


def RunSteps(api, props):  # pylint: disable=invalid-name
    path_to_update = str(props.path_to_update)
    cc_authors_on_rolls = props.cc_authors_on_rolls
    cc_reviewers_on_rolls = props.cc_reviewers_on_rolls
    cc_domains = props.cc_domains
    always_cc = props.always_cc

    props.checkout_options.use_trigger = False
    checkout = api.checkout(props.checkout_options)

    change = _update_project(api, checkout, path_to_update)
    if not change:
        return

    roll = api.roll_util.create_roll(
        project_name=path_to_update,
        old_revision=change.old,
        new_revision=change.new,
        proj_dir=change.dir,
        direction=change.direction,
    )

    authors = api.roll_util.authors(roll)

    max_commits_for_ccing = props.max_commits_for_ccing or 10
    if len(roll.commits) <= max_commits_for_ccing:
        cc = set()
        if cc_authors_on_rolls:
            cc.update(authors)
        if cc_reviewers_on_rolls:
            cc.update(api.roll_util.reviewers(roll))

        def include_cc(email):
            return api.roll_util.include_cc(
                email, cc_domains, checkout.gerrit_host()
            )

        # include_cc() writes steps, so we want things sorted before calling it.
        cc = sorted(set(cc))
        cc_emails = [x.email for x in cc if include_cc(x)]

        if always_cc:
            props.auto_roller_options.cc_emails.extend(cc_emails)
        else:
            props.auto_roller_options.cc_on_failure_emails.extend(cc_emails)

    author_override = None
    with api.step.nest('authors') as pres:
        pres.step_summary_text = repr(authors)
    if len(authors) == 1 and props.forge_author:
        author_override = attrs.asdict(
            api.roll_util.fake_author(next(iter(authors)))
        )

    # merge auto_roller_options and override_auto_roller_options.
    complete_auto_roller_options = api.roll_util.merge_auto_roller_overrides(
        props.auto_roller_options, props.override_auto_roller_options
    )

    change = api.auto_roller.attempt_roll(
        complete_auto_roller_options,
        repo_dir=checkout.root,
        commit_message=api.roll_util.message(roll),
        author_override=author_override,
    )

    return api.auto_roller.raw_result(change)


def GenTests(api) -> Generator[recipe_test_api.TestData, None, None]:
    """Create tests."""

    manifest = 'https://host.googlesource.com/manifest'

    def properties(api, path, dry_run=True, equivalent_remotes=(), **kwargs):
        props = InputProperties(**kwargs)
        props.checkout_options.CopyFrom(
            api.checkout.git_options(
                remote=manifest,
                equivalent_remotes=equivalent_remotes,
                match_branch=True,
            )
        )
        props.forge_author = True
        props.path_to_update = path
        props.auto_roller_options.CopyFrom(
            api.auto_roller.Options(dry_run=dry_run, remote=manifest)
        )

        return api.properties(props)

    def read_step_data():
        return api.step_data(
            'read manifest',
            api.file.read_text(
                """
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <!-- single-line comment -->
  <remote name="foo" fetch="sso://foo" review="sso://foo" />
  <remote name="bar" fetch="sso://bar" review="sso://bar" />
  <remote name="host" fetch=".." review="sso://host" />
  <remote name="dotdot-prefix" fetch="../prefix" review="sso://host/prefix" />
  <remote name="host-prefix" fetch="sso://host/prefix"
    review="sso://host/prefix" />
  <default remote="bar" />
  <project name="a" path="a1" remote="foo"
    revision="1111111111111111111111111111111111111111" upstream="main"/>
  <project name="b" path="b2"
    revision="2222222222222222222222222222222222222222" upstream="main"/>
  <!--
  multi
  line
  comment
  -->
  <project name="c" path="c3" revision="main"/>
  <project name="d" path="d4"
    revision="0000000000111111111122222222223333333333"/>
  <project name="e5" revision="refs/tags/e"/>
  <project name="f" path="f6" remote="host" revision="main"/>
  <project name="g" path="g7" remote="dotdot-prefix" revision="main"/>
  <project name="h" path="h8" remote="host-prefix" revision="main"/>
</manifest>
""".lstrip()
            ),
        )

    def commit_data(name):
        return api.roll_util.commit_data(
            name, api.roll_util.commit('a' * 40, 'foo\nbar')
        )

    yield api.test(
        'success',
        properties(api, path='a1', cc_authors_on_rolls=True, always_cc=True),
        api.checkout.ci_test_data(git_repo='https://foo.googlesource.com/a'),
        commit_data('a1'),
        read_step_data(),
        api.roll_util.forward_roll(),
        api.auto_roller.dry_run_success(),
    )

    yield api.test(
        'name-not-found',
        properties(api, path='missing'),
        api.checkout.ci_test_data(git_repo='https://bar.googlesource.com/b'),
        read_step_data(),
        status='FAILURE',
    )

    yield api.test(
        'equivalent',
        properties(
            api,
            path='b2',
            equivalent_remotes=(
                (
                    'https://equiv.googlesource.com/b',
                    'https://bar.googlesource.com/b',
                ),
            ),
            cc_reviewers_on_rolls=True,
        ),
        api.checkout.ci_test_data(git_repo='https://equiv.googlesource.com/b'),
        commit_data('b2'),
        read_step_data(),
        api.roll_util.forward_roll(),
        api.auto_roller.dry_run_success(),
    )

    yield api.test(
        'upstream-not-set',
        properties(api, path='c3'),
        api.checkout.ci_test_data(git_repo='https://bar.googlesource.com/c'),
        commit_data('c3'),
        read_step_data(),
        api.auto_roller.dry_run_success(),
    )

    yield api.test(
        'upstream-not-set-revision-not-branch',
        properties(api, path='d4'),
        api.checkout.ci_test_data(git_repo='https://bar.googlesource.com/c'),
        read_step_data(),
        status='FAILURE',
    )

    yield api.test(
        'no-trigger-with-upstream',
        properties(api, path='a1'),
        commit_data('a1'),
        read_step_data(),
        api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        ),
        api.roll_util.forward_roll(),
        api.auto_roller.dry_run_success(),
    )

    yield api.test(
        'no-trigger-with-revision-branch',
        properties(api, path='c3'),
        commit_data('c3'),
        read_step_data(),
        api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        ),
        api.auto_roller.dry_run_success(),
    )

    yield api.test(
        'no-trigger-with-revision-hash',
        properties(api, path='d4'),
        read_step_data(),
        api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        ),
        status='FAILURE',
    )

    yield api.test(
        'no-trigger-with-revision-tag',
        properties(api, path='e5'),
        read_step_data(),
        api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        ),
        status='FAILURE',
    )

    yield api.test(
        'backwards',
        properties(api, path='a1'),
        api.checkout.ci_test_data(git_repo='https://foo.googlesource.com/a'),
        read_step_data(),
        api.roll_util.backward_roll(),
    )

    yield api.test(
        'host-dot-dot',
        properties(api, path='f6'),
        api.checkout.ci_test_data(git_repo='https://host.googlesource.com/f'),
        commit_data('f6'),
        read_step_data(),
        api.auto_roller.dry_run_success(),
    )

    yield api.test(
        'dotdot-prefix',
        properties(api, path='g7'),
        api.checkout.ci_test_data(
            git_repo='https://host.googlesource.com/prefix/g'
        ),
        commit_data('g7'),
        read_step_data(),
        api.auto_roller.dry_run_success(),
    )

    yield api.test(
        'host-prefix',
        properties(api, path='h8'),
        api.checkout.ci_test_data(
            git_repo='https://host.googlesource.com/prefix/h'
        ),
        commit_data('h8'),
        read_step_data(),
        api.auto_roller.dry_run_success(),
    )
