# 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


class BazelRollApi(recipe_api.RecipeApi):

    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,
    ) -> list[roll_util_api.Roll]:
        workspace_path = self.workspace_path(
            checkout.root,
            git_repository.workspace_path,
        )
        git_repository.branch = git_repository.branch or 'main'

        new_revision = self.m.git_roll_util.resolve_new_revision(
            git_repository.remote,
            git_repository.branch,
            checkout.remotes_equivalent,
        )

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

        project_checkout = self.m.checkout(
            CheckoutOptions(
                remote=git_repository.remote,
                branch=git_repository.branch,
                use_trigger=False,
            ),
            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',
            )

        return [
            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
