# Copyright (c) 2023, JINGROW
# For license information, please see license.txt

from typing import Dict

import jingrow
from jingrow.model.page import Page

ALLOWED_CONFIG_PERMS = ["global", "restricted"]


class JcloudUserPermission(Page):
	# begin: auto-generated types
	# This code is auto-generated. Do not modify anything in this block.

	from typing import TYPE_CHECKING

	if TYPE_CHECKING:
		from jingrow.types import DF

		action: DF.Data | None
		config: DF.JSON | None
		document_name: DF.DynamicLink | None
		document_type: DF.Link | None
		group: DF.Link | None
		type: DF.Literal["User", "Group", "Config"]
		user: DF.Link | None
	# end: auto-generated types

	def validate(self):
		if self.type == "Config":
			self.validate_config()

	def validate_config(self):
		config = jingrow.parse_json(self.config)
		if not set(config.keys()).issubset(set(ALLOWED_CONFIG_PERMS)):
			jingrow.throw(f"Invalid config key. Allowed keys are: {format(ALLOWED_CONFIG_PERMS)}")


def has_user_permission(pg: str, name: str, action: str, groups: list = None):
	groups = groups or []
	user = jingrow.session.user
	allowed = False

	if not groups:
		groups = jingrow.get_all("Jcloud Permission Group User", {"user": user}, pluck="parent")

	# part of a group with access
	if jingrow.db.exists(
		"Jcloud User Permission",
		{
			"type": "Group",
			"group": ("in", groups),
			"document_type": pg,
			"document_name": name,
			"action": action,
		},
	):
		allowed = True

	# user has granular perm access
	if jingrow.db.exists(
		"Jcloud User Permission",
		{
			"type": "User",
			"user": user,
			"document_type": pg,
			"document_name": name,
			"action": action,
		},
	):
		allowed = True

	# has config perm access
	config = jingrow.db.get_value(
		"Jcloud User Permission", {"user": user, "type": "Config"}, "config", as_dict=True
	)
	if config:
		allowed = check_config_perm(
			jingrow.parse_json(config["config"]), pg, name, action, allowed
		)

	return allowed


def check_config_perm(
	config: Dict, pagetype: str, name: str, action: str, allowed: bool
):
	perm_types = config.keys()

	if "global" in perm_types:
		allowed = has_config_perm(config["global"], pagetype, name, action, allowed, "global")

	if "restricted" in perm_types:
		allowed = has_config_perm(
			config["restricted"], pagetype, name, action, allowed, "restricted"
		)

	return allowed


def has_config_perm(
	config: Dict, pagetype: str, name: str, action: str, allowed: bool, ptype: str
):
	if pagetype in config.keys():
		docnames = config[pagetype].keys()
		if name in docnames:
			name = name
		elif "*" in docnames:
			name = "*"
		else:
			return allowed

		if action in config[pagetype][name] or "*" in config[pagetype][name]:
			if ptype == "restricted":
				allowed = False
			elif ptype == "global":
				allowed = True

	return allowed
