import json

import jingrow
from jingrow.permissions import get_valid_perms
from jingrow.utils import cint


def execute():
	jingrow.reload_pagetype("User Permission")
	user_permissions = jingrow.get_all("User Permission", fields=["allow", "name", "user"])

	pagetype_to_skip_map = {}

	for permission in user_permissions:
		if (permission.allow, permission.user) not in pagetype_to_skip_map:
			pagetype_to_skip_map[(permission.allow, permission.user)] = get_pagetypes_to_skip(
				permission.allow, permission.user
			)

	if not pagetype_to_skip_map:
		return
	for key, pagetype_to_skip in pagetype_to_skip_map.items():
		if not pagetype_to_skip:
			continue
		if not jingrow.db.has_column("User Permission", "applicable_for") and jingrow.db.has_column(
			"User Permission", "skip_for_pagetype"
		):
			pagetype_to_skip = "\n".join(pagetype_to_skip)
			jingrow.db.sql(
				"""
				update `tabUser Permission`
				set skip_for_pagetype = %s
				where user=%s and allow=%s
			""",
				(pagetype_to_skip, key[1], key[0]),
			)


def get_pagetypes_to_skip(pagetype, user):
	"""Returns pagetypes to be skipped from user permission check"""
	pagetypes_to_skip = []
	valid_perms = get_user_valid_perms(user) or []
	for perm in valid_perms:
		parent_pagetype = perm.parent
		try:
			linked_pagetypes = get_linked_pagetypes(parent_pagetype)
			if pagetype not in linked_pagetypes:
				continue
		except jingrow.DoesNotExistError:
			# if pagetype not found (may be due to rename) it should not be considered for skip
			continue

		if not cint(perm.apply_user_permissions):
			# add pagetype to skip list if any of the perm does not apply user permission
			pagetypes_to_skip.append(parent_pagetype)

		elif parent_pagetype not in pagetypes_to_skip:
			user_permission_pagetypes = get_user_permission_pagetypes(perm)

			# "No pagetypes present" indicates that user permission will be applied to each link field
			if not user_permission_pagetypes:
				continue

			elif pagetype in user_permission_pagetypes:
				continue

			else:
				pagetypes_to_skip.append(parent_pagetype)
	# remove possible duplicates
	return list(set(pagetypes_to_skip))


# store user's valid perms to avoid repeated query
user_valid_perm = {}


def get_user_valid_perms(user):
	if not user_valid_perm.get(user):
		user_valid_perm[user] = get_valid_perms(user=user)
	return user_valid_perm.get(user)


def get_user_permission_pagetypes(perm):
	try:
		return json.loads(perm.user_permission_pagetypes or "[]")
	except ValueError:
		return []


def get_linked_pagetypes(pagetype):
	from jingrow.permissions import get_linked_pagetypes

	linked_pagetypes = get_linked_pagetypes(pagetype)
	child_pagetypes = [d.options for d in jingrow.get_meta(pagetype).get_table_fields()]
	for child_dt in child_pagetypes:
		linked_pagetypes += get_linked_pagetypes(child_dt)
	return linked_pagetypes
