# Copyright (c) 2015, JINGROW and Contributors
# License: MIT. See LICENSE

import jingrow
from jingrow import _
from jingrow.model import no_value_fields
from jingrow.model.page import Page


class Workflow(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
		from jingrow.workflow.pagetype.workflow_page_state.workflow_page_state import (
			WorkflowDocumentState,
		)
		from jingrow.workflow.pagetype.workflow_transition.workflow_transition import WorkflowTransition

		document_type: DF.Link
		is_active: DF.Check
		override_status: DF.Check
		send_email_alert: DF.Check
		states: DF.Table[WorkflowDocumentState]
		transitions: DF.Table[WorkflowTransition]
		workflow_data: DF.JSON | None
		workflow_name: DF.Data
		workflow_state_field: DF.Data

	# end: auto-generated types
	def validate(self):
		self.set_active()
		self.create_custom_field_for_workflow_state()
		self.update_default_workflow_status()
		self.validate_pagestatus()

	def on_update(self):
		jingrow.clear_cache(pagetype=self.document_type)

	def create_custom_field_for_workflow_state(self):
		jingrow.clear_cache(pagetype=self.document_type)
		meta = jingrow.get_meta(self.document_type)
		if not meta.get_field(self.workflow_state_field):
			# create custom field
			jingrow.get_pg(
				{
					"pagetype": "Custom Field",
					"dt": self.document_type,
					"__islocal": 1,
					"fieldname": self.workflow_state_field,
					"label": self.workflow_state_field.replace("_", " ").title(),
					"hidden": 1,
					"allow_on_submit": 1,
					"no_copy": 1,
					"fieldtype": "Link",
					"options": "Workflow State",
					"owner": "Administrator",
				}
			).save()

			jingrow.msgprint(
				_("Created Custom Field {0} in {1}").format(self.workflow_state_field, self.document_type)
			)

	def update_default_workflow_status(self):
		pagestatus_map = {}
		states = self.get("states")
		for d in states:
			if d.pg_status not in pagestatus_map:
				jingrow.db.sql(
					f"""
					UPDATE `tab{self.document_type}`
					SET `{self.workflow_state_field}` = %s
					WHERE ifnull(`{self.workflow_state_field}`, '') = ''
					AND `pagestatus` = %s
				""",
					(d.state, d.pg_status),
				)

				pagestatus_map[d.pg_status] = d.state

	def validate_pagestatus(self):
		def get_state(state):
			for s in self.states:
				if s.state == state:
					return s

			jingrow.throw(jingrow._("{0} not a valid State").format(state))

		for t in self.transitions:
			state = get_state(t.state)
			next_state = get_state(t.next_state)

			if state.pg_status == "2":
				jingrow.throw(
					jingrow._("Cannot change state of Cancelled Page. Transition row {0}").format(t.idx)
				)

			if state.pg_status == "1" and next_state.pg_status == "0":
				jingrow.throw(
					jingrow._(
						"Submitted Page cannot be converted back to draft. Transition row {0}"
					).format(t.idx)
				)

			if state.pg_status == "0" and next_state.pg_status == "2":
				jingrow.throw(jingrow._("Cannot cancel before submitting. See Transition {0}").format(t.idx))

	def set_active(self):
		if int(self.is_active or 0):
			# clear all other
			jingrow.db.sql(
				"""UPDATE `tabWorkflow` SET `is_active`=0
				WHERE `document_type`=%s""",
				self.document_type,
			)


@jingrow.whitelist()
def get_workflow_state_count(pagetype, workflow_state_field, states):
	jingrow.has_permission(pagetype=pagetype, ptype="read", throw=True)
	states = jingrow.parse_json(states)

	if workflow_state_field in jingrow.get_meta(pagetype).get_valid_columns():
		result = jingrow.get_all(
			pagetype,
			fields=[workflow_state_field, "count(*) as count"],
			filters={workflow_state_field: ["not in", states]},
			group_by=workflow_state_field,
		)
		return [r for r in result if r[workflow_state_field]]
