from django.http import HttpResponse
from django.test import RequestFactory
import httplib
import json
import mock
import owncloud
import requests
from nose import tools as nt

from addons.osfstorage.models import Region
from admin.rdm_custom_storage_location import views
from osf_tests.factories import (
    AuthUserFactory,
    InstitutionFactory,
)
from tests.base import AdminTestCase


class TestConnection(AdminTestCase):

    def setUp(self):
        super(TestConnection, self).setUp()
        self.institution = InstitutionFactory()
        self.user = AuthUserFactory()
        self.user.affiliated_institutions.add(self.institution)
        self.user.is_staff = True
        self.user.save()

    def view_post(self, params):
        request = RequestFactory().post(
            'fake_path',
            json.dumps(params),
            content_type='application/json'
        )
        request.is_ajax()
        request.user = self.user
        return views.TestConnectionView.as_view()(request)

    @mock.patch('owncloud.Client')
    def test_success_owncloud(self, mock_client):
        response = self.view_post({
            'owncloud_host': 'my-valid-host',
            'owncloud_username': 'my-valid-username',
            'owncloud_password': '<PASSWORD>',
            'owncloud_folder': 'my-valid-folder',
            'provider_short_name': 'owncloud',
        })
        nt.assert_equals(response.status_code, httplib.OK)
        nt.assert_in('Credentials are valid', response.content)

    @mock.patch('owncloud.Client')
    def test_success_nextcloud(self, mock_client):
        response = self.view_post({
            'nextcloud_host': 'my-valid-host',
            'nextcloud_username': 'my-valid-username',
            'nextcloud_password': '<PASSWORD>',
            'nextcloud_folder': 'my-valid-folder',
            'provider_short_name': 'nextcloud',
        })
        nt.assert_equals(response.status_code, httplib.OK)
        nt.assert_in('Credentials are valid', response.content)

    @mock.patch('owncloud.Client')
    def test_connection_error(self, mock_client):
        mock_client.side_effect = requests.exceptions.ConnectionError()

        response = self.view_post({
            'owncloud_host': 'cuzidontcare',
            'owncloud_username': 'my-valid-username',
            'owncloud_password': '<PASSWORD>',
            'owncloud_folder': 'my-valid-folder',
            'provider_short_name': 'owncloud',
        })
        nt.assert_equals(response.status_code, httplib.BAD_REQUEST)
        nt.assert_in('Invalid ownCloud server.', response.content)

    @mock.patch('owncloud.Client')
    def test_unauthorized(self, mock_client):
        res = HttpResponse(status=httplib.UNAUTHORIZED)
        mock_client.side_effect = owncloud.owncloud.HTTPResponseError(res)

        response = self.view_post({
            'owncloud_host': 'my-valid-host',
            'owncloud_username': 'bad-username',
            'owncloud_password': '<PASSWORD>',
            'owncloud_folder': 'my-valid-folder',
            'provider_short_name': 'owncloud',
        })
        nt.assert_equals(response.status_code, httplib.UNAUTHORIZED)
        nt.assert_in('ownCloud Login failed.', response.content)

    @mock.patch('owncloud.Client')
    def test_invalid_folder_id(self, mock_client):
        res = HttpResponse(status=httplib.BAD_REQUEST)
        mock_client.return_value.list.side_effect = owncloud.owncloud.HTTPResponseError(res)

        response = self.view_post({
            'owncloud_host': 'my-valid-host',
            'owncloud_username': 'my-valid-username',
            'owncloud_password': '<PASSWORD>',
            'owncloud_folder': 'my-valid-folder',
            'provider_short_name': 'owncloud',
        })
        nt.assert_equals(response.status_code, httplib.BAD_REQUEST)
        nt.assert_in('Invalid folder.', response.content)


class TestSaveCredentials(AdminTestCase):
    def setUp(self):
        super(TestSaveCredentials, self).setUp()
        self.institution = InstitutionFactory()
        self.user = AuthUserFactory()
        self.user.affiliated_institutions.add(self.institution)
        self.user.is_staff = True
        self.user.save()

    def view_post(self, params):
        request = RequestFactory().post(
            'fake_path',
            json.dumps(params),
            content_type='application/json'
        )
        request.is_ajax()
        request.user = self.user
        return views.SaveCredentialsView.as_view()(request)

    @mock.patch('admin.rdm_custom_storage_location.utils.test_owncloud_connection')
    def test_connection_fail(self, mock_testconnection):
        mock_testconnection.return_value = {'message': 'NG'}, httplib.BAD_REQUEST

        response = self.view_post({
            'storage_name': 'My storage',
            'owncloud_host': 'drop database;',
            'owncloud_username': 'invalid-user',
            'owncloud_password': '<PASSWORD>',
            'owncloud_folder': 'Hello World',
            'provider_short_name': 'owncloud',
        })

        nt.assert_equals(response.status_code, httplib.BAD_REQUEST)
        nt.assert_in('NG', response.content)
        nt.assert_false(Region.objects.filter(_id=self.institution._id).exists())

    @mock.patch('admin.rdm_custom_storage_location.utils.test_owncloud_connection')
    def test_success(self, mock_testconnection):
        mock_testconnection.return_value = {'message': 'Nice'}, httplib.OK

        response = self.view_post({
            'storage_name': 'My storage',
            'owncloud_host': 'valid.owncloud.net',
            'owncloud_username': 'admin',
            'owncloud_password': '<PASSWORD>',
            'owncloud_folder': 'reserved_for_osf',
            'provider_short_name': 'owncloud',
        })

        nt.assert_equals(response.status_code, httplib.OK)
        nt.assert_in('Saved credentials successfully!!', response.content)

        institution_storage = Region.objects.filter(_id=self.institution._id).first()
        nt.assert_is_not_none(institution_storage)
        nt.assert_equals(institution_storage.name, 'My storage')

        wb_credentials = institution_storage.waterbutler_credentials
        nt.assert_equals(wb_credentials['storage']['host'], 'https://valid.owncloud.net')
        nt.assert_equals(wb_credentials['storage']['username'], 'admin')
        nt.assert_equals(wb_credentials['storage']['password'], '<PASSWORD>')

        wb_settings = institution_storage.waterbutler_settings
        nt.assert_equals(wb_settings['storage']['provider'], 'owncloud')
        nt.assert_equals(wb_settings['storage']['folder'], '/reserved_for_osf/')
