# Copyright 2016 Google Inc.
#
# 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 datetime
import os
import sys

import mock
import oauth2client.client
import oauth2client.contrib.gce
import oauth2client.service_account
import pytest
from six.moves import reload_module

from google.auth import _oauth2client


DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
SERVICE_ACCOUNT_JSON_FILE = os.path.join(DATA_DIR, "service_account.json")


def test__convert_oauth2_credentials():
    old_credentials = oauth2client.client.OAuth2Credentials(
        "access_token",
        "client_id",
        "client_secret",
        "refresh_token",
        datetime.datetime.min,
        "token_uri",
        "user_agent",
        scopes="one two",
    )

    new_credentials = _oauth2client._convert_oauth2_credentials(old_credentials)

    assert new_credentials.token == old_credentials.access_token
    assert new_credentials._refresh_token == old_credentials.refresh_token
    assert new_credentials._client_id == old_credentials.client_id
    assert new_credentials._client_secret == old_credentials.client_secret
    assert new_credentials._token_uri == old_credentials.token_uri
    assert new_credentials.scopes == old_credentials.scopes


def test__convert_service_account_credentials():
    old_class = oauth2client.service_account.ServiceAccountCredentials
    old_credentials = old_class.from_json_keyfile_name(SERVICE_ACCOUNT_JSON_FILE)

    new_credentials = _oauth2client._convert_service_account_credentials(
        old_credentials
    )

    assert (
        new_credentials.service_account_email == old_credentials.service_account_email
    )
    assert new_credentials._signer.key_id == old_credentials._private_key_id
    assert new_credentials._token_uri == old_credentials.token_uri


def test__convert_service_account_credentials_with_jwt():
    old_class = oauth2client.service_account._JWTAccessCredentials
    old_credentials = old_class.from_json_keyfile_name(SERVICE_ACCOUNT_JSON_FILE)

    new_credentials = _oauth2client._convert_service_account_credentials(
        old_credentials
    )

    assert (
        new_credentials.service_account_email == old_credentials.service_account_email
    )
    assert new_credentials._signer.key_id == old_credentials._private_key_id
    assert new_credentials._token_uri == old_credentials.token_uri


def test__convert_gce_app_assertion_credentials():
    old_credentials = oauth2client.contrib.gce.AppAssertionCredentials(
        email="some_email"
    )

    new_credentials = _oauth2client._convert_gce_app_assertion_credentials(
        old_credentials
    )

    assert (
        new_credentials.service_account_email == old_credentials.service_account_email
    )


@pytest.fixture
def mock_oauth2client_gae_imports(mock_non_existent_module):
    mock_non_existent_module("google.appengine.api.app_identity")
    mock_non_existent_module("google.appengine.ext.ndb")
    mock_non_existent_module("google.appengine.ext.webapp.util")
    mock_non_existent_module("webapp2")


@mock.patch("google.auth.app_engine.app_identity")
def test__convert_appengine_app_assertion_credentials(
    app_identity, mock_oauth2client_gae_imports
):

    import oauth2client.contrib.appengine

    service_account_id = "service_account_id"
    old_credentials = oauth2client.contrib.appengine.AppAssertionCredentials(
        scope="one two", service_account_id=service_account_id
    )

    new_credentials = _oauth2client._convert_appengine_app_assertion_credentials(
        old_credentials
    )

    assert new_credentials.scopes == ["one", "two"]
    assert new_credentials._service_account_id == old_credentials.service_account_id


class FakeCredentials(object):
    pass


def test_convert_success():
    convert_function = mock.Mock(spec=["__call__"])
    conversion_map_patch = mock.patch.object(
        _oauth2client, "_CLASS_CONVERSION_MAP", {FakeCredentials: convert_function}
    )
    credentials = FakeCredentials()

    with conversion_map_patch:
        result = _oauth2client.convert(credentials)

    convert_function.assert_called_once_with(credentials)
    assert result == convert_function.return_value


def test_convert_not_found():
    with pytest.raises(ValueError) as excinfo:
        _oauth2client.convert("a string is not a real credentials class")

    assert excinfo.match("Unable to convert")


@pytest.fixture
def reset__oauth2client_module():
    """Reloads the _oauth2client module after a test."""
    reload_module(_oauth2client)


def test_import_has_app_engine(
    mock_oauth2client_gae_imports, reset__oauth2client_module
):
    reload_module(_oauth2client)
    assert _oauth2client._HAS_APPENGINE


def test_import_without_oauth2client(monkeypatch, reset__oauth2client_module):
    monkeypatch.setitem(sys.modules, "oauth2client", None)
    with pytest.raises(ImportError) as excinfo:
        reload_module(_oauth2client)

    assert excinfo.match("oauth2client")
