import re
from unittest.mock import patch

from odoo.tests.common import HttpCase, tagged


@tagged("-at_install", "post_install")
class TestAuthLDAP(HttpCase):

    def test_auth_ldap(self):
        def _get_ldap_dicts(self):
            template_user = self.env.ref("base.template_portal_user_id")
            return [
                {
                    "id": 1,
                    "company": (1, "YourCompany"),
                    "ldap_server": "127.0.0.1",
                    "ldap_server_port": 389,
                    "ldap_binddn": "cn=admin,dc=odoo,dc=com",
                    "ldap_password": "admin",
                    "ldap_filter": "cn=%s",
                    "ldap_base": "dc=odoo,dc=com",
                    "user": (template_user.id, template_user.name),
                    "create_user": True,
                    "ldap_tls": False,
                }
            ]

        def _authenticate(*args, **kwargs):
            return (
                "cn=test_ldap_user,dc=odoo,dc=com",
                {
                    "sn": [b"test_ldap_user"],
                    "cn": [b"test_ldap_user"],
                    "objectClass": [b"inetOrgPerson", b"top"],
                    "userPassword": [b"{MD5}CY9rzUYh03PK3k6DJie09g=="],
                },
            )

        self.env.cr.execute("SELECT id FROM res_users WHERE login = 'test_ldap_user'")
        self.assertFalse(self.env.cr.rowcount, "User should not be present")

        body = self.url_open("/web/login").text
        csrf = re.search(r'csrf_token: "(\w*?)"', body).group(1)

        with patch.object(self.registry["res.company.ldap"], "_get_ldap_dicts", _get_ldap_dicts),\
            patch.object(self.registry["res.company.ldap"], "_authenticate", _authenticate):
            res = self.url_open(
                f"{self.base_url()}/web/login",
                data={
                    "login": "test_ldap_user",
                    "password": "test",
                    "csrf_token": csrf,
                },
            )
            res.raise_for_status()

        self.assertTrue(res.session, "A session must exist at this point")

        self.env.cr.execute(
            "SELECT id FROM res_users WHERE login = %s and id = %s",
            ("test_ldap_user", res.session.uid))
        self.assertTrue(self.env.cr.rowcount, "User should be present")
