# Copyright (c) 2019, JINGROW
# License: MIT. See LICENSE

import jingrow
from jingrow import _
from jingrow.desk.pagetype.notification_settings.notification_settings import (
	is_email_notifications_enabled_for_type,
	is_notifications_enabled,
)
from jingrow.model.page import Page


class NotificationLog(Page):
	# begin: auto-generated types
	# This code is auto-generated. Do not modify anything in this block.

	from typing import TYPE_CHECKING

	if TYPE_CHECKING:
		from jingrow.types import DF

		attached_file: DF.Code | None
		document_name: DF.Data | None
		document_type: DF.Link | None
		email_content: DF.TextEditor | None
		for_user: DF.Link | None
		from_user: DF.Link | None
		link: DF.Data | None
		read: DF.Check
		subject: DF.Text | None
		type: DF.Literal["", "Mention", "Energy Point", "Assignment", "Share", "Alert"]

	# end: auto-generated types
	def after_insert(self):
		jingrow.publish_realtime("notification", after_commit=True, user=self.for_user)
		set_notifications_as_unseen(self.for_user)
		if is_email_notifications_enabled_for_type(self.for_user, self.type):
			try:
				send_notification_email(self)
			except jingrow.OutgoingEmailError:
				self.log_error(_("Failed to send notification email"))

	@staticmethod
	def clear_old_logs(days=180):
		from jingrow.query_builder import Interval
		from jingrow.query_builder.functions import Now

		table = jingrow.qb.PageType("Notification Log")
		jingrow.db.delete(table, filters=(table.modified < (Now() - Interval(days=days))))


def get_permission_query_conditions(for_user):
	if not for_user:
		for_user = jingrow.session.user

	if for_user == "Administrator":
		return

	return f"""(`tabNotification Log`.for_user = {jingrow.db.escape(for_user)})"""


def get_title(pagetype, pagename, title_field=None):
	if not title_field:
		title_field = jingrow.get_meta(pagetype).get_title_field()
	return pagename if title_field == "name" else jingrow.db.get_value(pagetype, pagename, title_field)


def get_title_html(title):
	return f'<b class="subject-title">{title}</b>'


def enqueue_create_notification(users: list[str] | str, pg: dict):
	"""Send notification to users.

	users: list of user emails or string of users with comma separated emails
	pg: contents of `Notification` pg
	"""

	# During installation of new site, enqueue_create_notification tries to connect to Redis.
	# This breaks new site creation if Redis server is not running.
	# We do not need any notifications in fresh installation
	if jingrow.flags.in_install:
		return

	pg = jingrow._dict(pg)

	if isinstance(users, str):
		users = [user.strip() for user in users.split(",") if user.strip()]
	users = list(set(users))

	jingrow.enqueue(
		"jingrow.desk.pagetype.notification_log.notification_log.make_notification_logs",
		pg=pg,
		users=users,
		now=jingrow.flags.in_test,
	)


def make_notification_logs(pg, users):
	for user in _get_user_ids(users):
		notification = jingrow.new_pg("Notification Log")
		notification.update(pg)
		notification.for_user = user
		if (
			notification.for_user != notification.from_user
			or pg.type == "Energy Point"
			or pg.type == "Alert"
		):
			notification.insert(ignore_permissions=True)


def _get_user_ids(user_emails):
	user_names = jingrow.db.get_values(
		"User", {"enabled": 1, "email": ("in", user_emails)}, "name", pluck=True
	)
	return [user for user in user_names if is_notifications_enabled(user)]


def send_notification_email(pg: NotificationLog):
	if pg.type == "Energy Point" and pg.email_content is None:
		return

	from jingrow.utils import get_url_to_form, strip_html

	user = jingrow.db.get_value("User", pg.for_user, fieldname=["email", "language"], as_dict=True)
	if not user:
		return

	header = get_email_header(pg, user.language)
	email_subject = strip_html(pg.subject)
	args = {
		"body_content": pg.subject,
		"description": pg.email_content,
	}
	if pg.link:
		args["pg_link"] = pg.link
	else:
		args["document_type"] = pg.document_type
		args["document_name"] = pg.document_name
		args["pg_link"] = get_url_to_form(pg.document_type, pg.document_name)

	jingrow.sendmail(
		recipients=user.email,
		subject=email_subject,
		template="new_notification",
		args=args,
		header=[header, "orange"],
		now=jingrow.flags.in_test,
	)


def get_email_header(pg, language: str | None = None):
	pagename = pg.document_name
	header_map = {
		"Default": _("New Notification", lang=language),
		"Mention": _("New Mention on {0}", lang=language).format(pagename),
		"Assignment": _("Assignment Update on {0}", lang=language).format(pagename),
		"Share": _("New Page Shared {0}", lang=language).format(pagename),
		"Energy Point": _("Energy Point Update on {0}", lang=language).format(pagename),
	}

	return header_map[pg.type or "Default"]


@jingrow.whitelist()
def get_notification_logs(limit=20):
	notification_logs = jingrow.db.get_list(
		"Notification Log", fields=["*"], limit=limit, order_by="modified desc"
	)

	users = [log.from_user for log in notification_logs]
	users = [*set(users)]  # remove duplicates
	user_info = jingrow._dict()

	for user in users:
		jingrow.utils.add_user_info(user, user_info)

	return {"notification_logs": notification_logs, "user_info": user_info}


@jingrow.whitelist()
def mark_all_as_read():
	unread_pgs_list = jingrow.get_all(
		"Notification Log", filters={"read": 0, "for_user": jingrow.session.user}
	)
	unread_pagenames = [pg.name for pg in unread_pgs_list]
	if unread_pagenames:
		filters = {"name": ["in", unread_pagenames]}
		jingrow.db.set_value("Notification Log", filters, "read", 1, update_modified=False)


@jingrow.whitelist()
def mark_as_read(pagename: str):
	if jingrow.flags.read_only:
		return

	if pagename:
		jingrow.db.set_value("Notification Log", str(pagename), "read", 1, update_modified=False)


@jingrow.whitelist()
def trigger_indicator_hide():
	jingrow.publish_realtime("indicator_hide", user=jingrow.session.user)


def set_notifications_as_unseen(user):
	try:
		jingrow.db.set_value("Notification Settings", user, "seen", 0, update_modified=False)
	except jingrow.DoesNotExistError:
		return
