from email import message
import json
import ssl
import aiohttp, os
from datetime import datetime
from discord import Embed
from exceptions import *
import yarl

class Player:
	original_request = ""
	requester_steam64 = ""
	current = {}
	steamid = {}
	play_on = {}
	def __init__(self, profile, requester_steam64, stats):
		self.requester_steam64 = requester_steam64
		self.original_request = profile
		self.stats = stats
		#потом надо будет сделать что профиль принимает все, а не только стим ид
		#api/profile/steam, ток там буква Z поэтому стоит поменять на секрет кей
		pass			
		
	async def GetSteamID(self):
		self.steamid = await self.GetSteamIDOfProfile(self.original_request)
		print(self.steam64)

	async def LoadProfile(self):
		self.current = await self.GetProfile(self.steam64)

	@property
	def steam64(self):
		return self.steamid.get('steam64', 0)

	@property
	def community_url(self):
		return self.steamid.get('community_url', '')

	@property
	def permition(self):
		return self.current.get("permition", {})

	@property
	def played_on_servers(self):
		return self.current.get("lastplay", {}) or self.current.get("gametime", {})

	@property
	def embed(self) -> Embed:
		if not self.current:
			raise NotLoadProfile
		# build header
		prepare_description = ""
		if self.current.get("play_on", {}):
			prepare_description = f"Сейчас играет на {self.stats['servers'][self.current['play_on']['server_id']]['name']}\n"
		elif self.current.get("lastplay", {}):
			selected_srv = "srv1"
			selected_timestamp = 0
			for srv, maps in self.current["lastplay"].items():
				for last_play in maps.values():
					if last_play > selected_timestamp:
						selected_srv = srv
						selected_timestamp = last_play
			prepare_description = f"Последняя игра на {self.stats['servers'][selected_srv]['name']}\nв {utime2human(selected_timestamp)}"
		else:
			prepare_description = "Не играл на фактах13"

		embed = Embed(
			title=self.current["steam_data"]["nickname"], 
			description=prepare_description, 
			url=self.current["steamids"]["community_url"])
		# set image
		embed.set_thumbnail(url = self.current["steam_data"]["avatar"])
		# Последняя игра на сервере
		if self.current.get("lastplay", {}):
			message = ""
			for maps in self.current["lastplay"].values():
				for map_name, last_play in maps.items():
					message += f"{workshopmap2bsp(map_name)} - {utime2human(last_play)}\n"
			embed.add_field(name="Последняя игра на серверах", value=message, inline=False)
		# Игрокое время
		if self.current.get("gametime", {}):
			message = ""
			for maps in self.current["gametime"].values():
				for map_name, play_time in maps.items():
					message += f"{workshopmap2bsp(map_name)} - {human_TIME(play_time)}\n"
			embed.add_field(name="Статистика по картам", value=message, inline=False)
		# Права
		if self.current.get("permition", {}):
			message = f"{self.current['permition']['status']} назначен {utime2human(self.current['permition']['u_timestamp']) if self.current['permition']['u_timestamp'] != 0 else 'с момента создания'}\n"
			if self.current['permition'].get('amount', 0) and self.current['permition'].get("u_timestamp", 0):
				message += f"окончание после {utime2human(self.current['permition']['u_timestamp'] + self.current['permition']['amount'])}\n"
			embed.add_field(name="Права на серверах", value=message, inline=False)
		# Бан
		if self.current.get("ban", {}):
			message = f"Ник: {self.current['ban']['player_name']}\n"
			message += f"Причина: {self.current['ban']['ban_reason']}\n"
			message += f"Время: {utime2human(self.current['ban']['ban_utime'])}\n"
			message += f"Кто забанил: {self.current['ban']['banned_by']} | <@{self.current['ban']['admin_info']['discord_id']}>\n"
			if self.current['ban']['active'] == True:
				if self.current['ban']['ban_length'] == 0:
					message += "Данный бан навсегда!\n"
				else:
					message += f"Дата разбана: {utime2human(self.current['ban']['ban_utime'] + self.current['ban']['ban_length_seconds'])}\n"
			embed.add_field(name="Имеется бан на сервере", value=message, inline=False)
			
		return embed

	def __str__(self):
		if not self.current:
			raise NotLoadProfile

		message = self.current["steamids"]["community_url"] + "\n"
		if "play_on" in self.current and self.current["play_on"]:
			message += f"Сейчас играет на {self.stats['servers'][self.current['play_on']['server_id']]['name']}\n"
		message += "\n"
		#тут должна быть последняя причина выхода с сервера, но она не релизована в бекенде
		message += "Последняя игра на серверах:\n"
		if "lastplay" in self.current and self.current["lastplay"]:
			for maps in self.current["lastplay"].values():
				for map_name, last_play in maps.items():
					message += f"{workshopmap2bsp(map_name)} - {utime2human(last_play)}\n"
		else:
			message += "Не играл у нас\n"
		message += "\n"
		#Далее игровое время бро
		if "gametime" in self.current and self.current["gametime"]:
			message += "Статистика по картам:\n"
			for maps in self.current["gametime"].values():
				for map_name, play_time in maps.items():
					message += f"{workshopmap2bsp(map_name)} - {human_TIME(play_time)}\n"
		message += "\n"
		#Далее идут проверка прав
		if "permition" in self.current and self.current["permition"]:
			message += f"Права: {self.current['permition']['status']} назначены {utime2human(self.current['permition']['u_timestamp']) if self.current['permition']['u_timestamp'] != 0 else 'с момента создания'}\n"
			if self.current['permition'].get('amount', 0) and self.current['permition'].get("u_timestamp", 0):
				message += f"Кончаются: {utime2human(self.current['permition']['u_timestamp'] + self.current['permition']['amount'])}\n"
			message += "\n"
		#Далее проверка бана
		if "ban" in self.current and self.current["ban"]:
			message += "ИМЕЕТСЯ БАН\n"
			message += f"Ник: {self.current['ban']['player_name']}\n"
			message += f"Причина: {self.current['ban']['ban_reason']}\n"
			message += f"Время: {utime2human(self.current['ban']['ban_utime'])}\n"
			message += f"Кто забанил: {self.current['ban']['banned_by']} | <@{self.current['ban']['admin_info']['discord_id']}>\n"
			if self.current['ban']['active'] == True:
				if self.current['ban']['ban_length'] == 0:
					message += "Данный бан навсегда!\n"
				else:
					message += f"Дата разбана: {utime2human(self.current['ban']['ban_utime'] + self.current['ban']['ban_length_seconds'])}\n"
			else:
				message += f"Кто разбанил: {'бан снялся со временем' if self.current['ban']['unbanned_by_id'] == 'STEAM_0:0:0' else self.current['ban']['unbanned_by_id']}\n"
		#Не реализованное получение числа скок был в бане
		return message

	async def GetSteamIDOfProfile(self, any:str):
		async with aiohttp.ClientSession(cookies={"secretkey":os.getenv("BACKEND_SECRETKEY")}) as session:
			async with session.post(url=f"{os.getenv('BACKEND_URL')}/api/profile/steam", json = {"any":any}, ssl=False) as response:
				try:
					response = await response.json()
				except:
					response = None
		if response == None:
			raise CannotCastToSteamID
		return response

	async def GetProfile(self, steam64):
		async with aiohttp.ClientSession(cookies={"secretkey":os.getenv("BACKEND_SECRETKEY")}) as session:
			async with session.get(f"{os.getenv('BACKEND_URL')}/api/profile?steam64={steam64}", ssl=False) as response:
				return await response.json()

	###############
	#admin commands
	###############
	async def vip(self, amount):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY"),
			"steam64": self.requester_steam64}) as session:
			async with session.post(f"{os.getenv('BACKEND_URL')}/api/admin/vip?steam64={self.steam64}&amount={amount}", ssl=False) as response:
				await response.text()
				if response.status == 409:
					return "Нельзя выдать випку по причине что пользователь имеет отличные правила от випа"
				elif response.status == 201:
					return "Випка была выдана"
				elif response.status == 205:
					return "Випка была продленна"
				elif response.status == 400:
					return "На том конце проишел хуй знает что"
				elif response.status == 403:
					raise LowPermition
				elif response.status == 406:
					raise AdminLowPermition
		raise UnknownBackendResponse

	async def unvip(self):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY"),
			"steam64": self.requester_steam64}) as session:
			async with session.delete(f"{os.getenv('BACKEND_URL')}/api/admin/vip?steam64={self.steam64}", ssl=False) as response:
				await response.text()
				if response.status == 409:
					return "У пользователя есть права, но они не вип, так что хуй"
				elif response.status == 200:
					return "Удалены права"
				elif response.status == 404:
					return "У пользователя нет прав и так"
				elif response.status == 400:
					return "На том конце проишел хуй знает что"
				elif response.status == 403:
					raise LowPermition
				elif response.status == 406:
					raise AdminLowPermition

		raise UnknownBackendResponse	

	async def kick(self, reason):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY"),
			"steam64": self.requester_steam64}) as session:
			async with session.post(f"{os.getenv('BACKEND_URL')}/api/admin/kick?steam64={self.steam64}", ssl=False) as response:
				result = await response.text()
				if response.status == 200:
					return "Кикнут с серверов"
				elif response.status == 404:
					raise NotFoundPlayerOnServer
				elif response.status == 403:
					raise LowPermition
				elif response.status == 406:
					raise AdminLowPermition
		raise UnknownBackendResponse

	async def mute(self):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY"),
			"steam64": self.requester_steam64}) as session:
			async with session.post(f"{os.getenv('BACKEND_URL')}/api/admin/mute?steam64={self.steam64}", ssl=False) as response:
				result = await response.text()
				if response.status == 200:
					return "Выключен микрофон"
				elif response.status == 404:
					raise NotFoundPlayerOnServer
				elif response.status == 403:
					raise LowPermition
				elif response.status == 406:
					raise AdminLowPermition
		raise UnknownBackendResponse

	async def unmute(self):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY"),
			"steam64": self.requester_steam64}) as session:
			async with session.delete(f"{os.getenv('BACKEND_URL')}/api/admin/mute?steam64={self.steam64}", ssl=False) as response:
				result = await response.text()
				if response.status == 200:
					return "Включен микрофон"
				elif response.status == 404:
					raise NotFoundPlayerOnServer
				elif response.status == 403:
					raise LowPermition
				elif response.status == 406:
					raise AdminLowPermition
		raise UnknownBackendResponse

	async def rcon(self, command, args):
		if not self.current:
			return "добродей дурачек забыл прогрузить профиль"

		if self.current.get("play_on", {}):
			server = self.current['play_on']['server_id']
			player_id = self.current['play_on']['player_id']
			final_command = f"{command} #{player_id} {args}"
			async with aiohttp.ClientSession(cookies={
				"secretkey":os.getenv("BACKEND_SECRETKEY"),
				"steam64": self.requester_steam64}) as session:
				async with session.post(f"{os.getenv('BACKEND_URL')}/api/admin/rcon?srv={server}&command={final_command}", ssl=False) as response:
					res = await response.text()
					if response.status == 200:
						return res
					elif response.status == 404:
						raise NotFoundPlayerOnServer
					elif response.status == 403:
						raise LowPermition
					elif response.status == 406:
						raise AdminLowPermition
		else:
			raise NotFoundPlayerOnServer

	async def ban(self, reason, minutes):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY"),
			"steam64": self.requester_steam64}) as session:
			async with session.post(f"{os.getenv('BACKEND_URL')}/api/admin/ban?steam64={self.steam64}&ban_reason={reason}&ban_length={minutes}", ssl=False) as response:
				ban_id = await response.text()
				if response.status == 201:
					return f"Игрок теперь забанен! Ид бана: #{ban_id}"
				elif response.status == 202:
					return f"Игрок уже в бане! Ид бана #{ban_id}"
				elif response.status == 404:
					raise NotFoundPlayerOnServer
				elif response.status == 403:
					raise LowPermition
				elif response.status == 406:
					raise AdminLowPermition
		raise UnknownBackendResponse

	async def unban(self):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY"),
			"steam64": self.requester_steam64}) as session:
			async with session.delete(f"{os.getenv('BACKEND_URL')}/api/admin/ban?steam64={self.steam64}", ssl=False) as response:
				ban_id = await response.text()
				if response.status == 200:
					return f"Игрок теперь разбанен!"
				elif response.status == 404:
					return f"Игрок не в бане("
				elif response.status == 403:
					raise LowPermition
				elif response.status == 406:
					raise AdminLowPermition
		raise UnknownBackendResponse

	###############
	#user command
	###############
	async def report(self, reason):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY"),
			"steam64": self.requester_steam64}) as session:
			async with session.post(f"{os.getenv('BACKEND_URL')}/api/profile/current/report?steam64={self.steam64}&text={reason}", ssl=False) as response:
				result = int(await response.text())
				if result == 0:
					return "Игрок с таким именем не играет на серверах в данный момент..."
				elif result < 0:
					return f"Падажди, следующий репорт можно отправить только после: {-1 * result} секунд"
				else:
					return f"Репорт отправлен!"

	async def freevip(self):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY"),
			"steam64": self.steam64}) as session:
			async with session.post(f"{os.getenv('BACKEND_URL')}/api/profile/current/freevip", ssl=False, json = {"discord_id": await self.GetDiscordId(), "vk_id":0}) as response:
				result = int(await response.text())
				if result == 0:
					return "Права на данном аккаунте уже имеются"
				elif result == 1:
					return "Развлекайся бро..."
				elif result > 1:
					return f"Ты не можешь получить бесплатную випку, стоит подождать {human_TIME(result)} с прошлой выдачи!"
				elif result < 0:
					return f"Чел... Тебе нужно еще наиграть на наших серверах {human_TIME(-1*result)} чтоб получить бесплатный вип!!!"
				else:
					return "Нихуя..."

	#############
	#discord sync
	#############
	async def GetDiscordId(self):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY")}) as session:
			async with session.get(f"{os.getenv('BACKEND_URL')}/api/discord/steam?steam64={self.steam64}", ssl = False) as response:
				try:
					discord_id = int(await response.text())
					if response.status == 404:
						raise Exception#код в ахуй
				except:
					discord_id = 0
				return discord_id

	async def CreateDiscordId(self, discord_id):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY")}) as session:
			async with session.post(f"{os.getenv('BACKEND_URL')}/api/discord?discord_id={discord_id}&steam64={self.steam64}", ssl = False) as response:
				result = await response.text()
				if response.status == 406:
					return False
				elif response.status == 201:
					return result
				else:
					return False

	async def RemoveDiscordId(self, discord_id):
		async with aiohttp.ClientSession(cookies={
			"secretkey":os.getenv("BACKEND_SECRETKEY")}) as session:
			async with session.delete(f"{os.getenv('BACKEND_URL')}/api/discord?discord_id={discord_id}", ssl = False) as response:
				result = await response.text()
				if response.status == 406:
					return False
				elif response.status == 200:
					return result
				else:
					return False


def workshopmap2bsp(map_name):
	return map_name.split('/')[-1:][0].split('.ugc')[0]

def utime2human(utime):
	return datetime.fromtimestamp(utime).strftime('%H:%M:%S %d.%m.%Y')

def human_TIME(seconds):
	m, s = divmod(int(seconds), 60)
	h, m = divmod(m, 60)
	d, h = divmod(h, 24)
	if not d:
		return "%d:%02d:%02d" % (h, m, s)
	elif d < 2:
		return "%d день %d:%02d:%02d" % (d ,h, m, s)
	else:
		return "%d дней %d:%02d:%02d" % (d ,h, m, s)

def ban2message(ban):
	message = f"Ник: {ban['player_name']}\n"
	message += f"Причина: {ban['ban_reason']}\n"
	message += f"Время: {utime2human(ban['ban_utime'])}\n"
	try:
		message += f"Кто забанил: {ban['banned_by']} | <@{ban['admin_info']['discord_id']}>\n"
	except:
		pass
	#что выше надо править
	if ban['active'] == True:
		if ban['ban_length'] == 0:
			message += "Данный бан навсегда!\n"
		else:
			message += f"Дата разбана: {utime2human(ban['ban_utime'] + ban['ban_length_seconds'])}\n"
	return message