# 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 MockCredentials(object):
    pass


def test_convert_success():
    convert_function = mock.Mock()
    conversion_map_patch = mock.patch.object(
        _oauth2client, '_CLASS_CONVERSION_MAP',
        {MockCredentials: convert_function})
    credentials = MockCredentials()

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