import os
import tempfile
import mock
import pytest
import yaml
import os_sdk_light as osl


@pytest.fixture
def change_dir():
    dir = os.getcwd()
    os.chdir(os.path.dirname(__file__))
    yield
    os.chdir(dir)


def test_no_cloud_config(change_dir):
    with pytest.raises(
            osl.exceptions.CannotConnectToCloud, match='Not enough params'):
        osl.get_client(0, 0, 0)


def test_invalid_auth_params():
    f = tempfile.NamedTemporaryFile(mode='w')
    data = yaml.safe_load(open('clouds.yaml'))
    data['clouds']['devstack']['auth']['password'] = 'fake'
    yaml.dump(data, f)
    with pytest.raises(
            osl.exceptions.CannotConnectToCloud,
            match='Authentication failed'):
        osl.get_client('devstack', 0, 0, config={'config_files': [f.name]})


def test_incorrect_auth_schema():
    f = tempfile.NamedTemporaryFile(mode='w')
    data = yaml.safe_load(open('clouds.yaml'))
    del data['clouds']['devstack']['auth']['password']
    yaml.dump(data, f)
    with pytest.raises(
            osl.exceptions.CannotConnectToCloud,
            match='Authentication failed'):
        osl.get_client('devstack', 0, 0, config={'config_files': [f.name]})


def test_empty_auth_schema():
    f = tempfile.NamedTemporaryFile(mode='w')
    data = yaml.safe_load(open('clouds.yaml'))
    del data['clouds']['devstack']['auth']['password']
    del data['clouds']['devstack']['auth']['username']
    yaml.dump(data, f)
    with pytest.raises(
            osl.exceptions.CannotConnectToCloud,
            match='Authentication failed'):
        osl.get_client('devstack', 0, 0, config={'config_files': [f.name]})


def test_get_endpoint_failed():
    with pytest.raises(
            osl.exceptions.CannotConnectToCloud,
            match='Failed to find service endpoint'):
        osl.get_client('devstack', 0, 0)


def test_incorrect_schema():
    f = tempfile.NamedTemporaryFile()
    with pytest.raises(
            osl.exceptions.SchemaError,
            match='cannot be read or invalid'):
        osl.get_client('devstack', 'compute', f.name)


def test_request_not_match_schema():
    compute = osl.get_client('devstack', 'compute', osl.schema('compute.yaml'))
    with pytest.raises(
            osl.exceptions.ValidationError,
            match='required parameter'):
        compute.flavors.create_flavor()
    with pytest.raises(
            osl.exceptions.ValidationError,
            match='required property'):
        compute.flavors.create_flavor(flavor={'flavor': {'name': 'test'}})


def test_response_not_match_schema():
    compute = osl.get_client('devstack', 'compute', osl.schema('compute.yaml'))
    with mock.patch(
            'bravado.http_future.HttpFuture._get_incoming_response') as r:
        resp = mock.MagicMock()
        resp.status_code = 200
        resp.json.return_value = {}
        r.return_value = resp
        with pytest.raises(
                osl.exceptions.ValidationError,
                match='required property'):
            compute.flavors.get_flavor(flavor_id='fake')


def test_not_defined_response():
    compute = osl.get_client('devstack', 'compute', osl.schema('compute.yaml'))
    with mock.patch(
            'bravado.requests_client.RequestsResponseAdapter') as resp_class:
        resp = mock.MagicMock()
        resp.status_code = 404
        resp.json.return_value = {}
        resp_class.return_value = resp
        try:
            compute.flavors.get_flavor(flavor_id='fake')
            pytest.fail('Exception must be thrown')
        except osl.exceptions.UnexpectedResponse as e:
            assert resp.status_code == e.status_code


def test_microversion_in_header():
    p = osl.get_client('devstack', 'placement', osl.schema('placement.yaml'))
    p.traits.get_traits()
