import datetime
import logging
import re
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from booker.models import Scanner
from asgiref.sync import sync_to_async
from channels.db import database_sync_to_async
from django.contrib.auth import get_user_model
from homelog.system_user import get_system_user
from homelog import settings
from django.core.exceptions import ObjectDoesNotExist

LOGGER = logging.getLogger(__name__)


class ScannerAnnounceConsumer(AsyncWebsocketConsumer):

    async def connect(self):
        self.group_name = 'scanner-announce'
        # join to group
        await self.channel_layer.group_add(self.group_name, self.channel_name)
        LOGGER.debug(f"send mqtt_subscribe to channel layer {settings.MQTT_CHANNEL_NAME} to answer on channel {self.group_name} (my channel is {self.channel_name})")
        await self.channel_layer.send(settings.MQTT_CHANNEL_NAME, {
            "type": "mqtt.subscribe",
            "topic": "barcodescanner/+/status",
            "group": self.group_name
        })
        LOGGER.debug("ScannerAnnounceConsumer initialized")
        await self.accept()

    async def receive(self, mqtt_message):
        pass

    async def disconnect(self, code):
        await self.channel_layer.send(settings.MQTT_CHANNEL_NAME, {
            "type": "mqtt.unsubscribe",
            "topic": "barcodescanner/#/status",
            "group": self.group_name
        })
        LOGGER.debug(f"Disconnect from scanner-announce, unsubscribing topic; code={code}")
        await self.channel_layer.group_discard(self.group_name, self.channel_name)

    async def distribute(self, event):
        valother = event['text']
        await self.send(text_data=valother)

    @database_sync_to_async
    def get_or_create_scanner(self, named_id, topic):
        scanner, created = Scanner.objects.get_or_create(named_id=named_id, defaults={
            'lwt_topic': topic,
            'last_online_ts': datetime.datetime.now(),
            'created_by': get_system_user(),
            'changed_by': get_system_user()
        })
        if created:
            LOGGER.debug(f"Created new scanner entry for {named_id}")
        else:
            LOGGER.debug(f"Updated scanner entry for {named_id}")
        return scanner

    async def mqtt_message(self, event):
        message = event['message']
        topic = message['topic']
        qos = message['qos']
        payload = message['payload']
        print('Received a message at topic: ', topic)
        print('with payload ', payload)
        print('and QOS ', qos)
        named_id = 'invalid'
        m = re.match(r'barcodescanner\/(barcodescan-[0-9,a-f]{6})\/status', topic)
        if m:
            named_id = m[1]
        await self.send(text_data=json.dumps({'message': payload, 'scanner': named_id, 'topic': topic}))
        LOGGER.debug(f"Got MQTT message from {topic} with payload {payload}")
        if payload == 'Online' or payload == 'online':
            scanner = await self.get_or_create_scanner(named_id=named_id, topic=topic)
