from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.contrib import messages
from django.conf import settings

from bcrypt import checkpw

import asyncio

from reportmonster_client import ReportMonsterClient


class ReportMonsterBackend(ModelBackend):
    async def _fetch_data(self, username: str):
        try:
            client = ReportMonsterClient(
                settings.REPORTMONSTER["Username"],
                settings.REPORTMONSTER["Password"],
                settings.REPORTMONSTER.get("Host", fallback="127.0.0.1"),
                settings.REPORTMONSTER.getint("Port", fallback=6789))

            try:
                await client.connect()
            except Exception as e:
                raise Exception("Something went wrong connecting to ReportMonster: " + repr(e))

            authresult = await client.auth()

            if authresult.error:
                raise Exception("Something went wrong authenticating with ReportMonster: " + response._raw)

            response = await client.write(f"user {settings.REPORTMONSTER['Vessel']} {username}")
            
            if response.error:
                raise Exception("Something went wrong fetching user details: " + response._raw)

            return response

        except Exception as e:
            messages.error(self.request, "Could not login. " + repr(e))

    def authenticate(self, request, username: str = None, password:str = None):
        self.request = request

        userdata = asyncio.run(asyncio.wait_for(self._fetch_data(username), 10))

        if not userdata or not userdata.content:
            return

        if checkpw(password.encode(), userdata.content["password"].encode()):
            user, _ = get_user_model().objects.get_or_create(email=username)
            user.save()
            return user
