# Copyright (c) 2021, JINGROW
# For license information, please see license.txt
from __future__ import annotations

import jingrow
import pytz
import sqlparse
from jingrow.core.pagetype.access_log.access_log import make_access_log
from jingrow.utils import (
	get_datetime,
	get_datetime_str,
	get_system_timezone,
)

from jcloud.agent import Agent

try:
	from jingrow.utils import convert_utc_to_user_timezone
except ImportError:
	from jingrow.utils import convert_utc_to_system_timezone as convert_utc_to_user_timezone


def execute(filters=None):
	jingrow.only_for(["System Manager", "Site Manager"])
	filters.database = jingrow.get_pg("Site", filters.site).fetch_info()["config"]["db_name"]

	make_access_log(
		pagetype="Site",
		document=filters.site,
		file_type="Binary Log",
		report_name="Binary Log Browser",
		filters=filters,
	)

	data = get_data(filters)

	columns = [
		{
			"fieldname": "timestamp",
			"label": jingrow._("Timestamp"),
			"fieldtype": "Datetime",
			"width": 160,
		},
		{
			"fieldname": "query",
			"label": jingrow._("Query"),
			"fieldtype": "Data",
			"width": 1200,
		},
	]
	return columns, data


def get_data(filters):
	server = jingrow.db.get_value("Site", filters.site, "server")
	database_server = jingrow.db.get_value("Server", server, "database_server")
	agent = Agent(database_server, "Database Server")

	data = {
		"database": filters.database,
		"start_datetime": convert_user_timezone_to_utc(filters.start_datetime),
		"stop_datetime": convert_user_timezone_to_utc(filters.stop_datetime),
		"search_pattern": filters.pattern,
		"max_lines": filters.max_lines or 4000,
	}

	files = agent.get("database/binary/logs")

	files_in_timespan = get_files_in_timespan(files, data["start_datetime"], data["stop_datetime"])

	results = []
	for file in files_in_timespan:
		rows = agent.post(f"database/binary/logs/{file}", data=data)
		for row in rows or []:
			if filters.format_queries:
				row["query"] = sqlparse.format(row["query"].strip(), keyword_case="upper", reindent=True)
			row["timestamp"] = get_datetime_str(convert_utc_to_user_timezone(get_datetime(row["timestamp"])))
			results.append(row)

			if len(results) > data["max_lines"]:
				return results

	return results


def get_files_in_timespan(files: list[dict[str, str]], start: str, stop: str) -> list[str]:
	files.sort(key=lambda f: f["modified"])

	files_in_timespan = []

	for file in files:
		if file["modified"] > stop:
			# This is last file that captures timespan
			# Include it and dont process any further.
			files_in_timespan.append(file["name"])
			break

		if start > file["modified"]:
			# Modified timestamp is *usually* last time when log file was touched,
			# i.e. last query logged on file
			continue

		files_in_timespan.append(file["name"])

	return files_in_timespan


def convert_user_timezone_to_utc(datetime):
	timezone = pytz.timezone(get_system_timezone())
	datetime = get_datetime(datetime)
	return get_datetime_str(timezone.localize(datetime).astimezone(pytz.utc))
