# Copyright (c) 2022, JINGROW
# License: MIT. See LICENSE

import json

import jingrow
from jingrow import _
from jingrow.config import get_modules_from_all_apps_for_user
from jingrow.model.page import Page
from jingrow.modules.export_file import export_to_files
from jingrow.query_builder import PageType


class Dashboard(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.desk.pagetype.dashboard_chart_link.dashboard_chart_link import DashboardChartLink
		from jingrow.desk.pagetype.number_card_link.number_card_link import NumberCardLink
		from jingrow.types import DF

		cards: DF.Table[NumberCardLink]
		chart_options: DF.Code | None
		charts: DF.Table[DashboardChartLink]
		dashboard_name: DF.Data
		is_default: DF.Check
		is_standard: DF.Check
		module: DF.Link | None

	# end: auto-generated types
	def on_update(self):
		if self.is_default:
			# make all other dashboards non-default
			DashBoard = PageType("Dashboard")

			jingrow.qb.update(DashBoard).set(DashBoard.is_default, 0).where(DashBoard.name != self.name).run()

		if jingrow.conf.developer_mode and self.is_standard:
			export_to_files(
				record_list=[["Dashboard", self.name, f"{self.module} Dashboard"]], record_module=self.module
			)

	def validate(self):
		if not jingrow.conf.developer_mode and self.is_standard:
			jingrow.throw(_("Cannot edit Standard Dashboards"))

		if self.is_standard:
			non_standard_pgs_map = {
				"Dashboard Chart": get_non_standard_charts_in_dashboard(self),
				"Number Card": get_non_standard_cards_in_dashboard(self),
			}

			if non_standard_pgs_map["Dashboard Chart"] or non_standard_pgs_map["Number Card"]:
				message = get_non_standard_warning_message(non_standard_pgs_map)
				jingrow.throw(message, title=_("Standard Not Set"), is_minimizable=True)

		self.validate_custom_options()

	def validate_custom_options(self):
		if self.chart_options:
			try:
				json.loads(self.chart_options)
			except ValueError as error:
				jingrow.throw(_("Invalid json added in the custom options: {0}").format(error))


def get_permission_query_conditions(user):
	if not user:
		user = jingrow.session.user

	if user == "Administrator" or "System Manager" in jingrow.get_roles(user):
		return

	module_not_set = " ifnull(`tabDashboard`.`module`, '') = '' "
	allowed_modules = [
		jingrow.db.escape(module.get("module_name")) for module in get_modules_from_all_apps_for_user()
	]
	if not allowed_modules:
		return module_not_set

	return f" (`tabDashboard`.`module` in ({','.join(allowed_modules)}) or {module_not_set}) "


@jingrow.whitelist()
def get_permitted_charts(dashboard_name):
	permitted_charts = []
	dashboard = jingrow.get_pg("Dashboard", dashboard_name)
	for chart in dashboard.charts:
		if jingrow.has_permission("Dashboard Chart", pg=chart.chart):
			chart_dict = jingrow._dict()
			chart_dict.update(chart.as_dict())

			if dashboard.get("chart_options"):
				chart_dict.custom_options = dashboard.get("chart_options")
			permitted_charts.append(chart_dict)

	return permitted_charts


@jingrow.whitelist()
def get_permitted_cards(dashboard_name):
	dashboard = jingrow.get_pg("Dashboard", dashboard_name)
	return [card for card in dashboard.cards if jingrow.has_permission("Number Card", pg=card.card)]


def get_non_standard_charts_in_dashboard(dashboard):
	non_standard_charts = [pg.name for pg in jingrow.get_list("Dashboard Chart", {"is_standard": 0})]
	return [chart_link.chart for chart_link in dashboard.charts if chart_link.chart in non_standard_charts]


def get_non_standard_cards_in_dashboard(dashboard):
	non_standard_cards = [pg.name for pg in jingrow.get_list("Number Card", {"is_standard": 0})]
	return [card_link.card for card_link in dashboard.cards if card_link.card in non_standard_cards]


def get_non_standard_warning_message(non_standard_pgs_map):
	message = _("""Please set the following documents in this Dashboard as standard first.""")

	def get_html(pgs, pagetype):
		html = f"<p>{jingrow.bold(pagetype)}</p>"
		for pg in pgs:
			html += f'<div><a href="/app/Form/{pagetype}/{pg}">{pg}</a></div>'
		html += "<br>"
		return html

	html = message + "<br>"

	for pagetype in non_standard_pgs_map:
		if non_standard_pgs_map[pagetype]:
			html += get_html(non_standard_pgs_map[pagetype], pagetype)

	return html
