# Copyright (c) 2018, JINGROW and Contributors
# License: MIT. See LICENSE
import json
import time
from contextlib import contextmanager

import jingrow
from jingrow.desk.query_report import generate_report_result, get_report_pg
from jingrow.query_builder.utils import db_type_is
from jingrow.tests.test_query_builder import run_only_if
from jingrow.tests.utils import JingrowTestCase, timeout


class TestPreparedReport(JingrowTestCase):
	@classmethod
	def tearDownClass(cls):
		for r in jingrow.get_all("Prepared Report", pluck="name"):
			jingrow.delete_pg("Prepared Report", r, force=True, delete_permanently=True)

		jingrow.db.commit()

	@timeout(seconds=20)
	def wait_for_status(self, report, status):
		jingrow.db.commit()  # Flush changes first
		while True:
			jingrow.db.rollback()  # read new data
			report.reload()
			if report.status == status:
				break
			time.sleep(0.5)

	def create_prepared_report(self, report=None, commit=True):
		pg = jingrow.get_pg(
			{
				"pagetype": "Prepared Report",
				"report_name": report or "Database Storage Usage By Tables",
			}
		).insert()

		if commit:
			jingrow.db.commit()

		return pg

	def test_queueing(self):
		pg = self.create_prepared_report()
		self.assertEqual("Queued", pg.status)
		self.assertTrue(pg.queued_at)

		self.wait_for_status(pg, "Completed")

		pg = jingrow.get_last_pg("Prepared Report")
		self.assertTrue(pg.job_id)
		self.assertTrue(pg.report_end_time)

	def test_prepared_data(self):
		pg = self.create_prepared_report()
		self.wait_for_status(pg, "Completed")

		prepared_data = json.loads(pg.get_prepared_data().decode("utf-8"))
		generated_data = generate_report_result(get_report_pg("Database Storage Usage By Tables"))
		self.assertEqual(len(prepared_data["columns"]), len(generated_data["columns"]))
		self.assertEqual(len(prepared_data["result"]), len(generated_data["result"]))
		self.assertEqual(len(prepared_data), len(generated_data))

	@run_only_if(db_type_is.MARIADB)
	def test_start_status_and_kill_jobs(self):
		with test_report(report_type="Query Report", query="select sleep(10)") as report:
			pg = self.create_prepared_report(report.name)
			self.wait_for_status(pg, "Started")
			job_id = pg.job_id

			pg.delete()
			time.sleep(1)
			job = jingrow.get_pg("RQ Job", job_id)
			self.assertEqual(job.status, "stopped")


@contextmanager
def test_report(**args):
	try:
		report = jingrow.new_pg("Report")
		report.update(args)
		if not report.report_name:
			report.report_name = jingrow.generate_hash()
		if not report.ref_pagetype:
			report.ref_pagetype = "ToDo"
		report.insert()
		jingrow.db.commit()
		yield report
	finally:
		report.delete()
