# Copyright (c) 2024, JINGROW
# See license.txt

import jingrow
from jingrow.tests.utils import JingrowTestCase

from jcloud.jcloud.pagetype.site.test_site import create_test_site
from jcloud.jcloud.pagetype.team.test_team import create_test_team


class TestJcloudRole(JingrowTestCase):
	def setUp(self):
		jingrow.set_user("Administrator")
		jingrow.db.delete("Jcloud Role")
		self.team_user = create_user("team@example.com")
		self.team = create_test_team(self.team_user.email)
		self.team_member = create_user("user123@example.com")
		self.team.append("team_members", {"user": self.team_member.name})
		self.team.save()
		self.admin_perm_role = create_permission_role(self.team.name)
		self.perm_role = create_permission_role(self.team.name)
		self.perm_role2 = create_permission_role(self.team.name)

	def tearDown(self):
		jingrow.set_user("Administrator")
		jingrow.delete_pg("Jcloud Role", self.perm_role.name, force=True)
		jingrow.delete_pg("Jcloud Role", self.perm_role2.name, force=True)
		jingrow.delete_pg("Team", self.team.name, force=True)
		jingrow.delete_pg("User", self.team_member.name, force=True)
		jingrow.delete_pg("User", self.team_user.name, force=True)
		jingrow.local._current_team = None

	def test_add_user(self):
		self.perm_role.add_user(self.team_member.name)
		perm_role_users = get_users(self.perm_role)
		perm_role_user_exists = any(
			self.team_member.name == perm_role_user.user for perm_role_user in perm_role_users
		)
		self.assertTrue(perm_role_user_exists)
		self.assertRaises(jingrow.ValidationError, self.perm_role.add_user, self.team_member.name)

	def test_remove_user(self):
		self.perm_role.add_user(self.team_member.name)
		self.perm_role.remove_user(self.team_member.name)
		perm_role_users = get_users(self.perm_role)
		perm_role_user_exists = any(
			self.team_member.name == perm_role_user.user for perm_role_user in perm_role_users
		)
		self.assertFalse(perm_role_user_exists)
		self.assertRaises(jingrow.ValidationError, self.perm_role.remove_user, self.team_member.name)

	def test_delete_role(self):
		perm = jingrow.new_pg("Jcloud Role Permission")
		perm.role = self.perm_role.name
		perm.team = self.team.name
		perm.save()

		self.perm_role.delete()
		self.assertFalse(jingrow.db.exists("Jcloud Role", self.perm_role.name))
		self.assertFalse(jingrow.db.get_all("Jcloud Role Permission", filters={"role": self.perm_role.name}))

	def test_delete_permissions(self):
		perm = jingrow.new_pg("Jcloud Role Permission")
		perm.role = self.perm_role.name
		perm.team = self.team.name
		perm.save()

		permissions = jingrow.get_all(
			"Jcloud Role Permission", filters={"role": self.perm_role.name}, pluck="name"
		)
		self.perm_role.delete_permissions(permissions)
		self.assertFalse(jingrow.db.get_all("Jcloud Role Permission", filters={"role": self.perm_role.name}))

	def test_get_list_with_permissions(self):
		from jcloud.api.client import get_list

		jingrow.set_user("Administrator")
		site1 = create_test_site(team=self.team.name)
		site2 = create_test_site(team=self.team.name)
		self.perm_role.add_user(self.team_user.name)
		self.perm_role2.add_user(self.team_user.name)
		jingrow.set_user(self.team_user.name)

		# no permissions added should show all records
		self.assertCountEqual(get_list("Site"), [])
		jingrow.set_user("Administrator")
		perm = jingrow.new_pg("Jcloud Role Permission")
		perm.role = self.perm_role.name
		perm.team = self.team.name
		perm.site = site1.name
		perm.save()
		jingrow.set_user(self.team_user.name)

		# permission for site1 added in the role
		self.assertEqual(get_list("Site"), [{"name": site1.name, "bench": site1.bench}])

		jingrow.set_user("Administrator")
		perm2 = jingrow.new_pg("Jcloud Role Permission")
		perm2.role = self.perm_role2.name
		perm2.team = self.team.name
		perm2.site = site2.name
		perm2.save()
		jingrow.set_user(self.team_user.name)

		# permission for site2 added in another role
		self.assertCountEqual(
			get_list("Site"),
			[
				{"name": site1.name, "bench": site1.bench},
				{"name": site2.name, "bench": site2.bench},
			],
		)

	def test_get_with_permissions(self):
		from jcloud.api.client import get

		jingrow.set_user("Administrator")
		site = create_test_site(team=self.team.name)
		site2 = create_test_site(team=self.team.name)
		self.perm_role.add_user(self.team_user.name)
		jingrow.set_user(self.team_user.name)

		# no permissions added should throw exception for both sites
		self.assertRaises(Exception, get, "Site", site.name)
		self.assertRaises(Exception, get, "Site", site2.name)

		jingrow.set_user("Administrator")
		perm = jingrow.new_pg("Jcloud Role Permission")
		perm.role = self.perm_role.name
		perm.team = self.team.name
		perm.site = site.name
		perm.save()
		jingrow.set_user(self.team_user.name)

		# permission for site added in the role
		self.assertEqual(get("Site", site.name).name, site.name)
		self.assertRaises(Exception, get, "Site", site2.name)

	def test_newly_created_sites_are_permitted_for_roles_with_allow_site_creation_and_existing_perms(
		self,
	):
		role = create_permission_role(self.team.name, allow_site_creation=1)

		# admin have insert perms (fw level), so adding admin as role user
		role.add_user("Administrator")
		role.add_user(self.team_user.name)
		jingrow.set_user("Administrator")

		# creating this site to add a permission
		site = create_test_site(team=self.team.name)

		jingrow.set_user(self.team_user.name)

		self.assertTrue(jingrow.db.exists("Jcloud Role Permission", {"site": site.name, "role": role.name}))

		jingrow.set_user("Administrator")
		jingrow.delete_pg("Jcloud Role", role.name, force=1)


# utils
def create_permission_role(team, allow_site_creation=0):
	import random

	pg = jingrow.new_pg("Jcloud Role")
	pg.title = "Test Role" + str(random.randint(1, 1000))
	pg.team = team
	pg.allow_site_creation = allow_site_creation
	pg.save()

	return pg


def create_user(email):
	if jingrow.db.exists("User", email):
		return jingrow.get_pg("User", email)
	user = jingrow.new_pg("User")
	user.email = email
	user.first_name = email.split("@")[0]
	user.save()
	return user


def get_users(role):
	return role.users
