# Copyright (c) 2019, JINGROW
# For license information, please see license.txt


import os
from functools import partial

import jingrow
from jingrow.core.pagetype.user.user import User
from jingrow.handler import is_whitelisted
from jingrow.utils import cint

from jcloude.access.support_access import has_support_access
from jcloude.runner import constants
from jcloude.utils import _get_current_team, _system_user


@jingrow.whitelist()
def upload_file():
	files = jingrow.request.files
	is_private = jingrow.form_dict.is_private
	pagetype = jingrow.form_dict.pagetype
	docname = jingrow.form_dict.docname
	fieldname = jingrow.form_dict.fieldname
	file_url = jingrow.form_dict.file_url
	folder = jingrow.form_dict.folder or "Home"
	method = jingrow.form_dict.method
	content = None
	filename = None

	if "file" in files:
		file = files["file"]
		content = file.stream.read()
		filename = file.filename

	jingrow.local.uploaded_file = content
	jingrow.local.uploaded_filename = filename

	if method:
		method = jingrow.get_attr(method)
		is_whitelisted(method)
		return method()
	ret = jingrow.get_pg(
		{
			"pagetype": "File",
			"attached_to_pagetype": pagetype,
			"attached_to_name": docname,
			"attached_to_field": fieldname,
			"folder": folder,
			"file_name": filename,
			"file_url": file_url,
			"is_private": cint(is_private),
			"content": content,
		}
	)
	ret.save()
	return ret


def on_session_creation():
	from jcloude.utils import get_current_team

	if (
		not jingrow.db.exists("Team", {"user": jingrow.session.user})
		and jingrow.session.data.user_type == "System User"
	):
		return

	try:
		team = get_current_team(get_pg=True)
		route = team.get_route_on_login()
		jingrow.local.response.update({"dashboard_route": route})
	except Exception:
		pass


def on_login(login_manager):
	if jingrow.session.user and jingrow.session.data and jingrow.session.data.user_type == "System User":
		return
	user = login_manager.user
	has_2fa = jingrow.db.get_value(
		"User 2FA", {"user": user, "enabled": 1}, ["last_verified_at"], as_dict=True
	)
	if has_2fa and (
		not has_2fa.get("last_verified_at")
		or has_2fa.get("last_verified_at") < jingrow.utils.add_to_date(None, seconds=-10)
	):
		jingrow.throw("Please re-login to verify your identity.")

	if not jingrow.db.exists("Team", {"user": jingrow.session.user, "enabled": 1}) and jingrow.db.exists(
		"Team", {"user": jingrow.session.user, "enabled": 0}
	):
		jingrow.db.set_value("Team", {"user": jingrow.session.user, "enabled": 0}, "enabled", 1)
		jingrow.db.commit()


def before_job():
	jingrow.local.team = _get_current_team
	jingrow.local.system_user = _system_user


def before_request():
	jingrow.local.team = _get_current_team
	jingrow.local.system_user = _system_user


def cleanup_ansible_tmp_files():
	import pathlib
	import shutil
	import time

	if not hasattr(constants, "DEFAULT_LOCAL_TMP"):
		return

	threshold = time.time() - 60 * 60  # >One hour old

	if os.environ.get("FRAPPE_BACKGROUND_WORKERS_NOFORK"):
		# Long running processes, don't cleanup
		threshold = time.time() - 2 * 24 * 60 * 60  # >2 days old

	temp_dir = pathlib.Path(constants.DEFAULT_LOCAL_TMP).parent
	ansible_dir = pathlib.Path.home() / ".ansible"
	# Avoid clearing unknown directories
	assert temp_dir.is_relative_to(ansible_dir) and temp_dir != ansible_dir

	for folder in temp_dir.iterdir():
		if folder.is_dir() and folder.stat().st_mtime < threshold:
			shutil.rmtree(folder)


def update_website_context(context):
	if (jingrow.request and jingrow.request.path.startswith("/docs")) and not jingrow.db.get_single_value(
		"Jcloude Settings", "publish_docs"
	):
		raise jingrow.DoesNotExistError


def has_permission(pg, ptype, user):
	from jcloude.utils import get_current_team

	if not user:
		user = jingrow.session.user

	user_type = jingrow.db.get_value("User", user, "user_type", cache=True)
	if user_type == "System User":
		return True

	if ptype == "create":
		return True

	team = get_current_team()
	child_team_members = [d.name for d in jingrow.db.get_all("Team", {"parent_team": team}, ["name"])]
	if pg.team == team or pg.team in child_team_members:
		return True

	if has_support_access(pg.pagetype, pg.name):
		return True

	return False


def get_permission_query_conditions_for_pagetype_and_user(pagetype, user):
	from jcloude.utils import get_current_team

	if not user:
		user = jingrow.session.user

	user_type = jingrow.db.get_value("User", user, "user_type", cache=True)
	if user_type == "System User":
		return ""

	team = get_current_team()

	return f"(`tab{pagetype}`.`team` = {jingrow.db.escape(team)})"


def get_permission_query_conditions_for_pagetype(pagetype):
	return partial(get_permission_query_conditions_for_pagetype_and_user, pagetype)


class CustomUser(User):
	dashboard_fields = ("full_name", "email", "user_image", "enabled", "user_type")

	@staticmethod
	def get_list_query(query):
		team = jingrow.local.team()
		allowed_users = [d.user for d in team.team_members]
		User = jingrow.qb.PageType("User")
		return query.where(User.name.isin(allowed_users))

	def after_rename(self, old_name, new_name, merge=False):
		"""
		Changes:
		- Excluding update operations on MyISAM tables
		"""
		myisam_tables = jingrow.db.sql_list(
			"""SELECT
			TABLE_NAME FROM information_schema.TABLES
		WHERE
			ENGINE='MyISAM'
		AND TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema')
		"""
		)
		tables = [x for x in jingrow.db.get_tables() if x not in myisam_tables]

		for tab in tables:
			desc = jingrow.db.get_table_columns_description(tab)
			has_fields = []
			for d in desc:
				if d.get("name") in ["owner", "modified_by"]:
					has_fields.append(d.get("name"))
			for field in has_fields:
				jingrow.db.sql(
					"""UPDATE `{}`
					SET `{}` = {}
					WHERE `{}` = {}""".format(tab, field, "%s", field, "%s"),
					(new_name, old_name),
				)

		for dt in ["Chat Profile", "Notification Settings"]:
			if jingrow.db.exists(dt, old_name):
				jingrow.rename_pg(dt, old_name, new_name, force=True, show_alert=False)

		# set email
		jingrow.db.sql(
			"""UPDATE `tabUser`
			SET email = %s
			WHERE name = %s""",
			(new_name, new_name),
		)


def before_after_migrate():
	# jingrow.clear_cache() on jcloude doesn't clear everything. See hooks.py
	jingrow.cache.flushall()
