import json

from werkzeug.routing import Rule

import jingrow
from jingrow import _
from jingrow.utils.data import sbool


def document_list(pagetype: str):
	if jingrow.form_dict.get("fields"):
		jingrow.form_dict["fields"] = json.loads(jingrow.form_dict["fields"])

	# set limit of records for jingrow.get_list
	jingrow.form_dict.setdefault(
		"limit_page_length",
		jingrow.form_dict.limit or jingrow.form_dict.limit_page_length or 20,
	)

	# convert strings to native types - only as_dict and debug accept bool
	for param in ["as_dict", "debug"]:
		param_val = jingrow.form_dict.get(param)
		if param_val is not None:
			jingrow.form_dict[param] = sbool(param_val)

	# evaluate jingrow.get_list
	return jingrow.call(jingrow.client.get_list, pagetype, **jingrow.form_dict)


def handle_rpc_call(method: str):
	import jingrow.handler

	method = method.split("/")[0]  # for backward compatiblity

	jingrow.form_dict.cmd = method
	return jingrow.handler.handle()


def create_pg(pagetype: str):
	data = get_request_form_data()
	data.pop("pagetype", None)
	return jingrow.new_pg(pagetype, **data).insert()


def update_pg(pagetype: str, name: str):
	data = get_request_form_data()

	pg = jingrow.get_pg(pagetype, name, for_update=True)
	if "flags" in data:
		del data["flags"]

	pg.update(data)
	pg.save()

	# check for child table pagetype
	if pg.get("parenttype"):
		jingrow.get_pg(pg.parenttype, pg.parent).save()

	return pg


def delete_pg(pagetype: str, name: str):
	# TODO: child pg handling
	jingrow.delete_pg(pagetype, name, ignore_missing=False)
	jingrow.response.http_status_code = 202
	return "ok"


def read_pg(pagetype: str, name: str):
	# Backward compatiblity
	if "run_method" in jingrow.form_dict:
		return execute_pg_method(pagetype, name)

	pg = jingrow.get_pg(pagetype, name)
	if not pg.has_permission("read"):
		raise jingrow.PermissionError
	pg.apply_fieldlevel_read_permissions()
	
	# 添加权限标记，与列表 API 保持一致
	try:
		pg._can_read = int(pg.has_permission("read"))
		pg._can_write = int(pg.has_permission("write"))
		pg._can_delete = int(pg.has_permission("delete"))
	except Exception:
		pg._can_read = 0
		pg._can_write = 0
		pg._can_delete = 0
	
	return pg


def execute_pg_method(pagetype: str, name: str, method: str | None = None):
	method = method or jingrow.form_dict.pop("run_method")
	pg = jingrow.get_pg(pagetype, name)
	pg.is_whitelisted(method)

	if jingrow.request.method == "GET":
		if not pg.has_permission("read"):
			jingrow.throw(_("Not permitted"), jingrow.PermissionError)
		return pg.run_method(method, **jingrow.form_dict)

	elif jingrow.request.method == "POST":
		if not pg.has_permission("write"):
			jingrow.throw(_("Not permitted"), jingrow.PermissionError)

		return pg.run_method(method, **jingrow.form_dict)


def get_request_form_data():
	if jingrow.form_dict.data is None:
		data = jingrow.safe_decode(jingrow.request.get_data())
	else:
		data = jingrow.form_dict.data

	try:
		return jingrow.parse_json(data)
	except ValueError:
		return jingrow.form_dict


url_rules = [
	Rule("/action/<path:method>", endpoint=handle_rpc_call),
	Rule("/data/<pagetype>", methods=["GET"], endpoint=document_list),
	Rule("/data/<pagetype>", methods=["POST"], endpoint=create_pg),
	Rule("/data/<pagetype>/<path:name>/", methods=["GET"], endpoint=read_pg),
	Rule("/data/<pagetype>/<path:name>/", methods=["PUT"], endpoint=update_pg),
	Rule("/data/<pagetype>/<path:name>/", methods=["DELETE"], endpoint=delete_pg),
	Rule("/data/<pagetype>/<path:name>/", methods=["POST"], endpoint=execute_pg_method),
]
