# Copyright (c) The stash contributors
#
# 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
#
#     http://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.
import json
import os
import subprocess
from typing import List


def print_debug(msg: str):
    """Print a message that is only visible when the GHA debug flag is set."""
    print(f"::debug::{msg}")


def set_output(name: str, value: str):
    """Set a GHA output variable."""
    with open(ensure_env_var("GITHUB_OUTPUT"), "a") as f:
        f.write(f"{name}={value}\n")


def ensure_env_var(var: str) -> str:
    """Return value of envvar `var`, throw if it's not set."""
    value = os.environ.get(var)
    if value is None or len(value) == 0:
        raise ValueError(f"Environment variable {var} is not set")
    return value


def run_checked(args, **kwargs):
    """Run command and capture it's output and check that it exits successfully."""
    result = subprocess.run(args, **kwargs, capture_output=True, check=True, text=True)
    return result


def jq(file: str, query: str, args: List[str] = []):
    """Wrapper to run `jq` query on a file on disk or on a JSON string."""
    if os.path.isfile(file):
        result = run_checked(["jq", *args, query, file])
    elif file.startswith("{"):
        result = run_checked(["jq", *args, query], input=file)
    else:
        raise ValueError("Input 'file' not found and not valid json string")

    return result


def gh_api(endpoint: str, method: str = "get", options: List[str] = []):
    """Wrapper to run `gh` REST API calls."""
    args = [
        "gh",
        "api",
        "-H",
        "Accept: application/vnd.github+json",
        "-H",
        "X-GitHub-Api-Version: 2022-11-28",
        f"--method={method}",
        *options,
        endpoint,
    ]
    result = run_checked(args)
    return result


def ensure_json(output: str):
    """Always return valid JSON."""
    if output.isspace():
        return json.loads("{}")
    else:
        return json.loads(output)


def get_workflow_stash(repo: str, run_id: str, name: str):
    ops = ["-q", ".artifacts | max_by(.updated_at | fromdate)", "-f", f"name={name}"]
    res = gh_api(f"repos/{repo}/actions/runs/{run_id}/artifacts", options=ops)
    print_debug(f"Returned stash: {res.stdout}")
    return ensure_json(res.stdout)


def get_branch_stash(repo: str, name: str, branch: str, repo_id: int):
    query = f"""
    .artifacts | map(select(
                    .expired == false and
                    .workflow_run.head_branch == "{branch}"
                    and .workflow_run.head_repository_id == {repo_id}))
               | max_by(.updated_at | fromdate)
    """
    ops = ["-q", query, "-f", f"name={name}"]
    res = gh_api(f"repos/{repo}/actions/artifacts", options=ops)
    print_debug(f"Returned stash: {res.stdout}")
    return ensure_json(res.stdout)
