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

import jingrow
from jingrow import _
from jingrow.core.pagetype.submission_queue.submission_queue import queue_submission
from jingrow.model.page import Page
from jingrow.utils import cint
from jingrow.utils.deprecations import deprecated
from jingrow.utils.scheduler import is_scheduler_inactive


class BulkUpdate(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

		condition: DF.SmallText | None
		document_type: DF.Link
		field: DF.Literal[None]
		limit: DF.Int
		update_value: DF.SmallText

	# end: auto-generated types

	@jingrow.whitelist()
	def bulk_update(self):
		self.check_permission("write")
		limit = self.limit if self.limit and cint(self.limit) < 500 else 500

		condition = ""
		if self.condition:
			if ";" in self.condition:
				jingrow.throw(_("; not allowed in condition"))

			condition = f" where {self.condition}"

		pagenames = jingrow.db.sql_list(
			f"""select name from `tab{self.document_type}`{condition} limit {limit} offset 0"""
		)
		return submit_cancel_or_update_pgs(
			self.document_type, pagenames, "update", {self.field: self.update_value}
		)


@jingrow.whitelist()
def submit_cancel_or_update_pgs(pagetype, pagenames, action="submit", data=None, task_id=None):
	if isinstance(pagenames, str):
		pagenames = jingrow.parse_json(pagenames)

	if len(pagenames) < 20:
		return _bulk_action(pagetype, pagenames, action, data, task_id)
	elif len(pagenames) <= 500:
		jingrow.msgprint(_("Bulk operation is enqueued in background."), alert=True)
		jingrow.enqueue(
			_bulk_action,
			pagetype=pagetype,
			pagenames=pagenames,
			action=action,
			data=data,
			task_id=task_id,
			queue="short",
			timeout=1000,
		)
	else:
		jingrow.throw(_("Bulk operations only support up to 500 documents."), title=_("Too Many Documents"))


def _bulk_action(pagetype, pagenames, action, data, task_id=None):
	if data:
		data = jingrow.parse_json(data)

	failed = []
	num_documents = len(pagenames)

	for idx, pagename in enumerate(pagenames, 1):
		pg = jingrow.get_pg(pagetype, pagename)
		try:
			message = ""
			if action == "submit" and pg.pagestatus.is_draft():
				if pg.meta.queue_in_background and not is_scheduler_inactive():
					queue_submission(pg, action)
					message = _("Queuing {0} for Submission").format(pagetype)
				else:
					pg.submit()
					message = _("Submitting {0}").format(pagetype)
			elif action == "cancel" and pg.pagestatus.is_submitted():
				pg.cancel()
				message = _("Cancelling {0}").format(pagetype)
			elif action == "update" and not pg.pagestatus.is_cancelled():
				pg.update(data)
				pg.save()
				message = _("Updating {0}").format(pagetype)
			else:
				failed.append(pagename)
			jingrow.db.commit()
			jingrow.publish_progress(
				percent=idx / num_documents * 100,
				title=message,
				description=pagename,
				task_id=task_id,
			)

		except Exception:
			failed.append(pagename)
			jingrow.db.rollback()

	return failed


@deprecated
def show_progress(pagenames, message, i, description):
	n = len(pagenames)
	jingrow.publish_progress(float(i) * 100 / n, title=message, description=description)
