import jingrow
from jingrow.model.page import get_controller
from jingrow.utils.caching import redis_cache
from jingrow.website.page_renderers.base_template_page import BaseTemplatePage
from jingrow.website.router import (
	get_pagetypes_with_web_view,
	get_page_info_from_web_page_with_dynamic_routes,
)
from jingrow.website.utils import cache_html


class DocumentPage(BaseTemplatePage):
	def can_render(self):
		"""
		Find a document with matching `route` from all pagetypes with `has_web_view`=1
		"""
		if self.search_in_pagetypes_with_web_view():
			return True

		if self.search_web_page_dynamic_routes():
			return True

		return False

	def search_in_pagetypes_with_web_view(self):
		if document := _find_matching_document_webview(self.path):
			self.pagetype, self.pagename = document
			pg = jingrow.get_cached_pg(self.pagetype, self.pagename)
			return pg.meta.allow_guest_to_view or pg.has_permission() or jingrow.has_website_permission(pg)

	def search_web_page_dynamic_routes(self):
		d = get_page_info_from_web_page_with_dynamic_routes(self.path)
		if d:
			self.pagetype = d.pagetype
			self.pagename = d.name
			return True
		else:
			return False

	def render(self):
		html = self.get_html()
		html = self.add_csrf_token(html)

		return self.build_response(html)

	@cache_html
	def get_html(self):
		self.pg = jingrow.get_pg(self.pagetype, self.pagename)
		self.init_context()
		self.update_context()
		self.post_process_context()
		return jingrow.get_template(self.template_path).render(self.context)

	def update_context(self):
		self.context.pg = self.pg
		self.context.update(self.context.pg.as_dict())
		self.context.update(self.context.pg.get_page_info())

		self.template_path = self.context.template or self.template_path

		if not self.template_path:
			self.template_path = self.context.pg.meta.get_web_template()

		if hasattr(self.pg, "get_context"):
			ret = self.pg.get_context(self.context)

			if ret:
				self.context.update(ret)

		for prop in ("no_cache", "sitemap"):
			if prop not in self.context:
				self.context[prop] = getattr(self.pg, prop, False)

	@staticmethod
	def get_condition_field(meta):
		condition_field = None
		if meta.is_published_field:
			condition_field = meta.is_published_field
		elif not meta.custom:
			controller = get_controller(meta.name)
			condition_field = controller.website.condition_field

		return condition_field


@redis_cache(ttl=60 * 60)
def _find_matching_document_webview(route: str) -> tuple[str, str] | None:
	for pagetype in get_pagetypes_with_web_view():
		filters = dict(route=route)
		meta = jingrow.get_meta(pagetype)
		condition_field = DocumentPage.get_condition_field(meta)

		if condition_field:
			filters[condition_field] = 1

		try:
			pagename = None
			if meta.is_virtual:
				if doclist := jingrow.get_all(pagetype, filters=filters, fields=["name"], limit=1):
					pagename = doclist[0].get("name")
			else:
				pagename = jingrow.db.get_value(pagetype, filters, "name")

			if pagename:
				return (pagetype, pagename)
		except Exception as e:
			if not jingrow.db.is_missing_column(e):
				raise e
