# Copyright (c) 2023, JINGROW and Contributors
# See license.txt

import re

import jingrow
import jingrow.recorder
from jingrow.core.pagetype.recorder.recorder import _optimize_query, serialize_request
from jingrow.query_builder.utils import db_type_is
from jingrow.recorder import get as get_recorder_data
from jingrow.tests.test_query_builder import run_only_if
from jingrow.tests.utils import JingrowTestCase
from jingrow.utils import set_request


class TestRecorder(JingrowTestCase):
	def setUp(self):
		self.start_recoder()

	def tearDown(self) -> None:
		jingrow.recorder.stop()

	def start_recoder(self):
		jingrow.recorder.stop()
		jingrow.recorder.delete()
		set_request(path="/api/action/ping")
		jingrow.recorder.start()
		jingrow.recorder.record()

	def stop_recorder(self):
		jingrow.recorder.dump()

	def test_recorder_list(self):
		jingrow.get_all("User")  # trigger one query
		self.stop_recorder()
		requests = jingrow.get_all("Recorder")
		self.assertGreaterEqual(len(requests), 1)
		request = jingrow.get_pg("Recorder", requests[0].name)
		self.assertGreaterEqual(len(request.sql_queries), 1)
		queries = [sql_query.query for sql_query in request.sql_queries]
		match_flag = 0
		for query in queries:
			if bool(re.match("^[select.*from `tabUser`]", query, flags=re.IGNORECASE)):
				match_flag = 1
				break
		self.assertEqual(match_flag, 1)

	def test_recorder_list_filters(self):
		user = jingrow.qb.PageType("User")
		jingrow.qb.from_(user).select("name").run()
		self.stop_recorder()

		set_request(path="/api/action/abc")
		jingrow.recorder.start()
		jingrow.recorder.record()
		jingrow.get_all("User")
		self.stop_recorder()

		requests = jingrow.get_list(
			"Recorder", filters={"path": ("like", "/api/action/ping"), "number_of_queries": 1}
		)
		self.assertGreaterEqual(len(requests), 1)
		requests = jingrow.get_list("Recorder", filters={"path": ("like", "/api/action/test")})
		self.assertEqual(len(requests), 0)

		requests = jingrow.get_list("Recorder", filters={"method": "GET"})
		self.assertGreaterEqual(len(requests), 1)
		requests = jingrow.get_list("Recorder", filters={"method": "POST"})
		self.assertEqual(len(requests), 0)

		requests = jingrow.get_list("Recorder", order_by="path desc")
		self.assertEqual(requests[0].path, "/api/action/ping")

	def test_recorder_serialization(self):
		jingrow.get_all("User")  # trigger one query
		self.stop_recorder()
		requests = jingrow.get_all("Recorder")
		request_pg = get_recorder_data(requests[0].name)
		self.assertIsInstance(serialize_request(request_pg), dict)


class TestQueryOptimization(JingrowTestCase):
	@run_only_if(db_type_is.MARIADB)
	def test_query_optimizer(self):
		suggested_index = _optimize_query(
			"""select name from
			`tabUser` u
			join `tabHas Role` r
			on r.parent = u.name
			where email='xyz'
			and modified > '2023'
			and bio like '%xyz%'
			"""
		)
		self.assertEqual(suggested_index.table, "tabUser")
		self.assertEqual(suggested_index.column, "email")
