# Copyright 2016 Google LLC
#
# 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 io
import json
import os
import subprocess

import mock
import pytest

from google.auth import _cloud_sdk
from google.auth import environment_vars
from google.auth import exceptions


DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
AUTHORIZED_USER_FILE = os.path.join(DATA_DIR, "authorized_user.json")

with io.open(AUTHORIZED_USER_FILE) as fh:
    AUTHORIZED_USER_FILE_DATA = json.load(fh)

SERVICE_ACCOUNT_FILE = os.path.join(DATA_DIR, "service_account.json")

with io.open(SERVICE_ACCOUNT_FILE) as fh:
    SERVICE_ACCOUNT_FILE_DATA = json.load(fh)

with io.open(os.path.join(DATA_DIR, "cloud_sdk_config.json"), "rb") as fh:
    CLOUD_SDK_CONFIG_FILE_DATA = fh.read()


@pytest.mark.parametrize(
    "data, expected_project_id",
    [
        (CLOUD_SDK_CONFIG_FILE_DATA, "example-project"),
        (b"I am some bad json", None),
        (b"{}", None),
    ],
)
def test_get_project_id(data, expected_project_id):
    check_output_patch = mock.patch(
        "subprocess.check_output", autospec=True, return_value=data
    )

    with check_output_patch as check_output:
        project_id = _cloud_sdk.get_project_id()

    assert project_id == expected_project_id
    assert check_output.called


@mock.patch(
    "subprocess.check_output",
    autospec=True,
    side_effect=subprocess.CalledProcessError(-1, None),
)
def test_get_project_id_call_error(check_output):
    project_id = _cloud_sdk.get_project_id()
    assert project_id is None
    assert check_output.called


def test__run_subprocess_ignore_stderr():
    command = [
        "python",
        "-c",
        "from __future__ import print_function;"
        + "import sys;"
        + "print('error', file=sys.stderr);"
        + "print('output', file=sys.stdout)",
    ]

    # If we ignore stderr, then the output only has stdout
    output = _cloud_sdk._run_subprocess_ignore_stderr(command)
    assert output == b"output\n"

    # If we pipe stderr to stdout, then the output is mixed with stdout and stderr.
    output = subprocess.check_output(command, stderr=subprocess.STDOUT)
    assert output == b"output\nerror\n" or output == b"error\noutput\n"


@mock.patch("os.name", new="nt")
def test_get_project_id_windows():
    check_output_patch = mock.patch(
        "subprocess.check_output",
        autospec=True,
        return_value=CLOUD_SDK_CONFIG_FILE_DATA,
    )

    with check_output_patch as check_output:
        project_id = _cloud_sdk.get_project_id()

    assert project_id == "example-project"
    assert check_output.called
    # Make sure the executable is `gcloud.cmd`.
    args = check_output.call_args[0]
    command = args[0]
    executable = command[0]
    assert executable == "gcloud.cmd"


@mock.patch("google.auth._cloud_sdk.get_config_path", autospec=True)
def test_get_application_default_credentials_path(get_config_dir):
    config_path = "config_path"
    get_config_dir.return_value = config_path
    credentials_path = _cloud_sdk.get_application_default_credentials_path()
    assert credentials_path == os.path.join(
        config_path, _cloud_sdk._CREDENTIALS_FILENAME
    )


def test_get_config_path_env_var(monkeypatch):
    config_path_sentinel = "config_path"
    monkeypatch.setenv(environment_vars.CLOUD_SDK_CONFIG_DIR, config_path_sentinel)
    config_path = _cloud_sdk.get_config_path()
    assert config_path == config_path_sentinel


@mock.patch("os.path.expanduser")
def test_get_config_path_unix(expanduser):
    expanduser.side_effect = lambda path: path

    config_path = _cloud_sdk.get_config_path()

    assert os.path.split(config_path) == ("~/.config", _cloud_sdk._CONFIG_DIRECTORY)


@mock.patch("os.name", new="nt")
def test_get_config_path_windows(monkeypatch):
    appdata = "appdata"
    monkeypatch.setenv(_cloud_sdk._WINDOWS_CONFIG_ROOT_ENV_VAR, appdata)

    config_path = _cloud_sdk.get_config_path()

    assert os.path.split(config_path) == (appdata, _cloud_sdk._CONFIG_DIRECTORY)


@mock.patch("os.name", new="nt")
def test_get_config_path_no_appdata(monkeypatch):
    monkeypatch.delenv(_cloud_sdk._WINDOWS_CONFIG_ROOT_ENV_VAR, raising=False)
    monkeypatch.setenv("SystemDrive", "G:")

    config_path = _cloud_sdk.get_config_path()

    assert os.path.split(config_path) == ("G:/\\", _cloud_sdk._CONFIG_DIRECTORY)


@mock.patch("os.name", new="nt")
@mock.patch("subprocess.check_output", autospec=True)
def test_get_auth_access_token_windows(check_output):
    check_output.return_value = b"access_token\n"

    token = _cloud_sdk.get_auth_access_token()
    assert token == "access_token"
    check_output.assert_called_with(
        ("gcloud.cmd", "auth", "print-access-token"), stderr=subprocess.STDOUT
    )


@mock.patch("subprocess.check_output", autospec=True)
def test_get_auth_access_token_with_account(check_output):
    check_output.return_value = b"access_token\n"

    token = _cloud_sdk.get_auth_access_token(account="account")
    assert token == "access_token"
    check_output.assert_called_with(
        ("gcloud", "auth", "print-access-token", "--account=account"),
        stderr=subprocess.STDOUT,
    )


@mock.patch("subprocess.check_output", autospec=True)
def test_get_auth_access_token_with_exception(check_output):
    check_output.side_effect = OSError()

    with pytest.raises(exceptions.UserAccessTokenError):
        _cloud_sdk.get_auth_access_token(account="account")
