# Copyright 2024 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.

from __future__ import annotations

import configparser
import dataclasses
import io
import re
from typing import TYPE_CHECKING

from PB.recipe_modules.pigweed.checkout.options import (
    Options as CheckoutOptions,
)
from recipe_engine import recipe_api

if TYPE_CHECKING:  # pragma: no cover
    from typing import Generator
    from PB.recipe_modules.pigweed.bazel_roll.git_repository import (
        GitRepository,
    )
    from recipe_engine import config_types
    from RECIPE_MODULES.pigweed.checkout import api as checkout_api
    from RECIPE_MODULES.pigweed.roll_util import api as roll_util_api


@dataclasses.dataclass
class RevisionChange:
    old: str
    new: str


class BazelRollApi(recipe_api.RecipeApi):

    RevisionChange = RevisionChange

    def workspace_path(
        self,
        root: config_types.Path,
        value: str,
    ) -> config_types.Path:
        """Figure out the location of the WORKSPACE or MODULE.bazel file.

        If value is '', look for root / 'WORKSPACE' and root / 'MODULE.bazel'.
        If exactly one exists, return it. If not, error out.

        If root / value is a file, return it.

        If root / value is a directory, set root = root / value and apply the
        above logic. This enables applying this logic to subdirectories.

        Args:
            api: Recipe API object.
            root: Checkout root.
            value: Relative path specified in properties.

        Returns:
            Path to the WORKSPACE or MODULE.bazel file.
        """
        if value:
            value_path = root / value
            self.m.path.mock_add_file(value_path)
            if self.m.path.isfile(value_path):
                return value_path
            elif self.m.path.isdir(value_path):  # pragma: no cover
                root = value_path
            else:
                self.m.step.empty(  # pragma: no cover
                    f'{value_path} does not exist',
                    status='FAILURE',
                )

        workspace = root / 'WORKSPACE'
        module_bazel = root / 'MODULE.bazel'

        self.m.path.mock_add_file(workspace)

        if self.m.path.isfile(module_bazel) and self.m.path.isfile(workspace):
            self.m.step.empty(  # pragma: no cover
                f'{module_bazel} and {workspace} both exist',
                status='FAILURE',
            )

        if self.m.path.isfile(module_bazel):
            return module_bazel  # pragma: no cover

        if self.m.path.isfile(workspace):
            return workspace

        self.m.step.empty(  # pragma: no cover
            'no WORKSPACE or MODULE.bazel file found',
            status='FAILURE',
        )

    def update_git_repository(
        self,
        checkout: checkout_self.m.CheckoutContext,
        git_repository: GitRepository,
    ) -> dict[str, self.m.roll_util.Roll]:
        workspace_path = self.workspace_path(
            checkout.root,
            git_repository.workspace_path,
        )
        git_repository.branch = git_repository.branch or 'main'

        new_revision: Optional[str] = None

        # First, try to get new_revision from the trigger.
        bb_remote: Optional[str] = None
        commit: common_pb2.GitilesCommit = (
            self.m.buildbucket.build.input.gitiles_commit
        )
        if commit and commit.project:
            new_revision = commit.id
            host: str = commit.host
            bb_remote: str = f'https://{host}/{commit.project}'

        # If we still don't have a revision then it wasn't in the trigger.
        # (Perhaps this was manually triggered.) In this case we update to the
        # property-specified branch HEAD.
        if new_revision is None:
            new_revision = git_repository.branch

        # If this was triggered by a gitiles poller, check that the triggering
        # repository matches project_remote. Exception: allow a trigger to be
        # for the top-level project instead.
        use_trigger_for_project = True

        if bb_remote:
            if checkout.remotes_equivalent(checkout.options.remote, bb_remote):
                use_trigger_for_project = False

            elif not checkout.remotes_equivalent(
                git_repository.remote,
                bb_remote,
            ):
                self.m.step.empty(
                    'triggering repository ({}) does not match project remote '
                    '({})'.format(bb_remote, git_repository.remote),
                    status='FAILURE',
                )

        project_dir = self.m.path.start_dir / 'project'

        project_checkout = self.m.checkout(
            CheckoutOptions(
                remote=git_repository.remote,
                branch=git_repository.branch,
                use_trigger=use_trigger_for_project,
            ),
            root=project_dir,
        )

        # In case new_revision is a branch name we need to retrieve the hash it
        # resolves to.
        if not re.search(r'^[0-9a-f]{40}$', new_revision):
            new_revision = self.m.checkout.get_revision(
                project_dir, 'get new revision', test_data='2' * 40
            )

        update_result = self.m.bazel.update_commit_hash(
            checkout=checkout,
            project_remote=git_repository.remote,
            new_revision=new_revision,
            path=workspace_path,
        )
        if not update_result:
            self.m.step.empty('failed to update commit hash', status='FAILURE')

        direction = self.m.roll_util.get_roll_direction(
            project_dir, update_result.old_revision, new_revision
        )

        # If the primary roll is not necessary or is backwards we can exit
        # immediately.
        if not self.m.roll_util.can_roll(direction):
            self.m.roll_util.skip_roll_step(
                git_repository.remote, update_result.old_revision, new_revision
            )
            return

        project_name = git_repository.name or update_result.project_name
        if not project_name:
            self.m.step.empty(
                f'could not find name line in {workspace_path}',
                status='FAILURE',
            )

        rolls: dict[str, self.m.roll_util.Roll] = {
            workspace_path: self.m.roll_util.create_roll(
                project_name=project_name,
                old_revision=update_result.old_revision,
                new_revision=new_revision,
                proj_dir=project_dir,
                direction=direction,
            ),
        }

        return rolls
