# -*- coding: utf-8; -*-
#
# This file is part of Superdesk.
#
# Copyright 2013, 2014 Sourcefabric z.u. and contributors.
#
# For the full copyright and license information, please see the
# AUTHORS and LICENSE files distributed with this source code, or
# at https://www.sourcefabric.org/superdesk/license

import os
from unittest import mock
from unittest.mock import MagicMock

from apps.auth.errors import CredentialsAuthError
from superdesk.errors import SuperdeskApiError
from superdesk.tests import TestCase
from superdesk import get_resource_service
from apps.ldap.commands import ImportUserProfileFromADCommand


if os.environ.get("LDAP_SERVER", ""):

    def get_mock_connection():
        """Create a mock ldap connection object.

        :return {object}: mock ldap connection object.
        """
        connection = MagicMock()
        connection.search(return_value=True)
        connection.response = [
            {
                "attributes": {
                    "sn": ["Bar"],
                    "givenName": ["Foo"],
                    "displayName": ["Foo Bar"],
                    "ipPhone": "+1234567890",
                    "email": "foo@bar.com",
                }
            }
        ]

        return connection

    @mock.patch("apps.ldap.ldap.Connection", return_value=get_mock_connection())
    class ImportUsersTestCase(TestCase):
        """for testing import user using ldap."""

        def test_import_user_using_command(self, mock_ldap_connection):
            user = {"username": "user", "password": "pwd", "user_to_import": "barf"}
            cmd = ImportUserProfileFromADCommand()

            cmd.run(user["username"], user["password"], user["user_to_import"])
            auth_user = get_resource_service("auth_db").authenticate({"username": "barf", "password": "dummy"})
            self.assertEqual(auth_user["username"], user["user_to_import"])

            cmd.run(user["username"], user["password"], "BARF")
            auth_user2 = get_resource_service("auth_db").authenticate({"username": "barf", "password": "dummy"})
            self.assertEqual(auth_user2["username"], user["user_to_import"])

            self.assertEqual(auth_user2["_id"], auth_user["_id"])

        @mock.patch("apps.ldap.ldap.get_user", return_value={"username": "user"})
        def test_import_profile_for_already_imported_user_raises_exception(self, mock_ldap_connection, mock_get_user):
            with self.assertRaises(SuperdeskApiError) as context:
                service = get_resource_service("import_profile")
                doc = {"username": "user", "password": "pwd", "profile_to_import": "barf"}
                users = service.post([doc])
                self.assertIsNotNone(users)
                self.assertEqual(len(users), 1)
                doc = {"username": "user", "password": "pwd", "profile_to_import": "BARF "}
                service.post([doc])

            ex = context.exception
            self.assertEqual(ex.message, "User already exists in the system.")
            self.assertEqual(ex.status_code, 400)
            self.assertDictEqual(ex.payload, {"profile_to_import": 1})

        @mock.patch("apps.ldap.ldap.get_user", return_value={"username": "user1"})
        def test_import_user_by_not_logged_in_user_raises_exception(self, mock_ldap_connection, mock_get_user):
            with self.assertRaises(SuperdeskApiError) as context:
                service = get_resource_service("import_profile")
                doc = {"username": "user", "password": "pwd", "profile_to_import": "barf"}
                service.post([doc])

            ex = context.exception
            self.assertEqual(ex.message, "Invalid Credentials.")
            self.assertEqual(ex.status_code, 403)
            self.assertDictEqual(ex.payload, {"credentials": 1})

        @mock.patch(
            "apps.ldap.ldap.ADAuth.authenticate_and_fetch_profile",
            side_effect=CredentialsAuthError(credentials={"username": "test"}, error="test"),
        )
        @mock.patch("apps.ldap.ldap.get_user", return_value={"username": "user"})
        def test_user_import_profile_with_invalid_credentials(self, mock_ldap_connection, mock_auth, mock_get_user):
            with self.assertRaises(SuperdeskApiError) as context:
                service = get_resource_service("import_profile")
                doc = {"username": "user", "password": "pwd", "profile_to_import": "barf"}
                service.post([doc])

            ex = context.exception
            self.assertEqual(ex.message, "Invalid Credentials.")
            self.assertEqual(ex.status_code, 403)
            self.assertDictEqual(ex.payload, {"credentials": 1})
