# 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')
