import json

from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
from django.contrib.auth.models import User
from muzak.auth import get_user_from_token
from channels.db import database_sync_to_async
from playlist.models import Session, Track, Vote
import random
import logging


class SessionConsumer(WebsocketConsumer):
	def connect(self):
		self.session_id = self.scope["url_route"]["kwargs"]["session_id"]
		self.session_name = f"session_{self.session_id}"
		self.logger = logging.getLogger(self.session_name)
		logging.basicConfig(filename=self.session_name+'.log', level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s', filemode='w')

		async_to_sync(self.channel_layer.group_add)(
			self.session_name, self.channel_name
		)
		self.accept()

	def disconnect(self, close_code):
		# Leave room group
		async_to_sync(self.channel_layer.group_discard)(
			self.session_name, self.channel_name
		)

	# Receive message from WebSocket
	def receive(self, text_data):
		user = self.scope["user"] # Waarschijnlijk altijd AnonymousUser
		#self.logger.info(self.scope)
		sessionId = self.scope["url_route"].get("kwargs", {}).get("session_id", None)

		text_data_json = json.loads(text_data)

		# Niet lachen, middleware is moeilijk oké?
		token = text_data_json.get("token")
		if token:
			user = get_user_from_token(token, log=False)
		session = Session.objects.get(session_id=sessionId)

		action = text_data_json.get("action", None)
		if action == "message":
			message = text_data_json["message"]
			# Send message to room group
			async_to_sync(self.channel_layer.group_send)(
				self.session_name, {"type": "chat.message", "message": str(user) + ": " + message}
			)
		if action == "login":
			self.logger.info(f"Announced: {user}")
			async_to_sync(self.channel_layer.group_send)(
				self.session_name, {"type": "announce", "user": { "id": user.id, "username": user.username}}
			)
		if action == "vote":
			points = text_data_json.get("points", None)
			track = session.current_track;
			vote = None
			try:
				vote = Vote.objects.get(user=user, track=track, session=session)
				vote.points = points
				self.logger.info(f"Updated vote for {track} by {user} to {points} points")
				vote.save()
			except Vote.DoesNotExist:
				vote = Vote.objects.create(user=user, track=track, points=points, session=session)
				self.logger.info(f"Created vote for {track} by {user} for {points} points")
				vote.save()
			except Exception as e:
				self.logger.error(f"Error voting on {track} by {user} for {points} points: {e}")
			if vote:
				async_to_sync(self.channel_layer.group_send)(
					self.session_name, {"type": "voted", "user": { "id": user.id, "username": user.username}, "track": track.id, "points": points}
				)
		if action == "start":
			async_to_sync(self.channel_layer.group_send)(
				self.session_name, {"type": "announce.start"}
			)
		if action == "next":
			random.seed(session.seed)
			tracks = Track.objects.order_by("?")
			next = False
			if session.current_track:
				for track in tracks:
					if next:
						session.current_track = track
						next = False
						break
					if session.current_track == track:
						next = True
				if next:
					# We didnt get a next track, so it must have been the last one
					session.current_track = None
			else:
				session.current_track = tracks.first()
			session.save()
			if session.current_track is None:
				async_to_sync(self.channel_layer.group_send)(
					self.session_name, {"type": "announce.done"}
				)
			else:
				async_to_sync(self.channel_layer.group_send)(
					self.session_name, {"type": "announce.track"}
				)


	def announce(self, event):
		user = event["user"]
		self.send(text_data=json.dumps({"joined": user}))

	# TODO: maybe this could be one function.
	def announce_track(self, event):
		self.send(text_data=json.dumps({"track": {}}))
	def announce_done(self, event):
		self.send(text_data=json.dumps({"done": {}}))
	def announce_start(self, event):
		self.send(text_data=json.dumps({"start": {}}))

	def voted(self, event):
		user = event["user"]
		#self.session_name, {"type": "voted", "user": { "id": user.id, "username": user.username}, "track": track.id, "points": points}
		self.send(text_data=json.dumps({"voted": { "id": user["id"], "username": user["username"], "points": event["points"], "track": event["track"]}}))


	# Receive message from room group
	def chat_message(self, event):
		message = event["message"]

		self.logger.info(self.scope["user"])

		# Send message to WebSocket
		self.send(text_data=json.dumps({"message": message}))
