# Copyright (c) 2019, JINGROW and Contributors
# License: MIT. See LICENSE
import os
from unittest.mock import patch

import jingrow
import jingrow.utils
from jingrow.core.pagetype.pagetype.test_pagetype import new_pagetype
from jingrow.custom.pagetype.customize_form.test_customize_form import TestCustomizeForm
from jingrow.desk.notifications import get_open_count
from jingrow.tests.utils import JingrowTestCase, patch_hooks


class TestDashboardConnections(JingrowTestCase):
	@patch.dict(jingrow.conf, {"developer_mode": 1})
	def setUp(self):
		delete_test_data()
		create_test_data()

	@patch.dict(jingrow.conf, {"developer_mode": 1})
	def tearDown(self):
		delete_test_data()

	def test_internal_link_count(self):
		earth = jingrow.get_pg(
			{
				"pagetype": "Test Pagetype B With Child Table With Link To Pagetype A",
				"title": "Earth",
			}
		)
		earth.append(
			"child_table",
			{
				"title": "Earth",
			},
		)
		earth.insert()

		mars = jingrow.get_pg(
			{
				"pagetype": "Test Pagetype A With Child Table With Link To Pagetype B",
				"title": "Mars",
			}
		)
		mars.append(
			"child_table",
			{"title": "Mars", "test_pagetype_b_with_test_child_table_with_link_to_pagetype_a": "Earth"},
		)
		mars.insert()

		expected_open_count = {
			"count": {
				"external_links_found": [],
				"internal_links_found": [
					{
						"count": 1,
						"pagetype": "Test Pagetype B With Child Table With Link To Pagetype A",
						"names": ["Earth"],
						"open_count": 0,
					}
				],
			}
		}

		with patch.object(
			mars.meta,
			"get_dashboard_data",
			return_value=get_dashboard_for_test_pagetype_a_with_test_child_table_with_link_to_pagetype_b(),
		):
			self.assertEqual(
				get_open_count("Test Pagetype A With Child Table With Link To Pagetype B", "Mars"),
				expected_open_count,
			)

	def test_external_link_count(self):
		saturn = jingrow.get_pg(
			{
				"pagetype": "Test Pagetype A With Child Table With Link To Pagetype B",
				"title": "Saturn",
			}
		)
		saturn.append(
			"child_table",
			{
				"title": "Saturn",
			},
		)
		saturn.insert()

		pluto = jingrow.get_pg(
			{
				"pagetype": "Test Pagetype B With Child Table With Link To Pagetype A",
				"title": "Pluto",
			}
		)
		pluto.append(
			"child_table",
			{"title": "Pluto", "test_pagetype_a_with_test_child_table_with_link_to_pagetype_b": "Saturn"},
		)
		pluto.insert()

		expected_open_count = {
			"count": {
				"external_links_found": [
					{
						"pagetype": "Test Pagetype B With Child Table With Link To Pagetype A",
						"open_count": 0,
						"count": 1,
					}
				],
				"internal_links_found": [],
			}
		}

		with patch.object(
			saturn.meta,
			"get_dashboard_data",
			return_value=get_dashboard_for_test_pagetype_a_with_test_child_table_with_link_to_pagetype_b(),
		):
			self.assertEqual(
				get_open_count("Test Pagetype A With Child Table With Link To Pagetype B", "Saturn"),
				expected_open_count,
			)

	def test_external_pagetype_link_with_dashboard_override(self):
		# add a custom links
		todo = TestCustomizeForm().get_customize_form("ToDo")
		todo.append("links", dict(link_pagetype="Test Pagetype D", link_fieldname="doclink", group="Test"))
		todo.append("links", dict(link_pagetype="Test Pagetype E", link_fieldname="todo", group="Test"))
		todo.run_method("save_customization")

		# create a test pg
		todo_pg = jingrow.get_pg(dict(pagetype="ToDo", description="test")).insert()
		jingrow.get_pg(dict(pagetype="Test Pagetype D", title="d-001", doclink=todo_pg.name)).insert()
		jingrow.get_pg(dict(pagetype="Test Pagetype E", title="e-001", todo=todo_pg.name)).insert()

		connections = get_open_count("ToDo", todo_pg.name)["count"]
		self.assertEqual(len(connections["external_links_found"]), 2)

		# Change standard fieldname, see if all custom links still work
		with patch_hooks(
			{
				"override_pagetype_dashboards": {
					"ToDo": ["jingrow.tests.test_dashboard_connections.get_dashboard_for_todo"]
				}
			}
		):
			connections = get_open_count("ToDo", todo_pg.name)["count"]
			self.assertEqual(len(connections["external_links_found"]), 2)

		# remove the custom links
		todo = TestCustomizeForm().get_customize_form("ToDo")
		todo.links = todo.links[:-2]
		todo.run_method("save_customization")


def create_test_data():
	create_test_child_table_with_link_to_pagetype_a()
	create_test_child_table_with_link_to_pagetype_b()
	create_test_pagetype_a_with_test_child_table_with_link_to_pagetype_b()
	create_test_pagetype_b_with_test_child_table_with_link_to_pagetype_a()
	create_linked_pagetypes()
	add_links_in_child_tables()


def delete_test_data():
	pagetypes = [
		"Test Child Table With Link To Pagetype A",
		"Test Child Table With Link To Pagetype B",
		"Test Pagetype A With Child Table With Link To Pagetype B",
		"Test Pagetype B With Child Table With Link To Pagetype A",
		"Test Pagetype D",
		"Test Pagetype E",
	]
	for pagetype in pagetypes:
		if jingrow.db.table_exists(pagetype):
			jingrow.db.delete(pagetype)
			jingrow.delete_pg("PageType", pagetype, force=True)


def create_test_child_table_with_link_to_pagetype_a():
	new_pagetype(
		"Test Child Table With Link To Pagetype A",
		istable=1,
		fields=[{"fieldname": "title", "fieldtype": "Data", "label": "Title", "reqd": 1, "unique": 1}],
		custom=False,
		autoname="field:title",
		naming_rule="By fieldname",
	).insert(ignore_if_duplicate=True)


def create_test_child_table_with_link_to_pagetype_b():
	new_pagetype(
		"Test Child Table With Link To Pagetype B",
		istable=1,
		fields=[{"fieldname": "title", "fieldtype": "Data", "label": "Title", "reqd": 1, "unique": 1}],
		custom=False,
		autoname="field:title",
		naming_rule="By fieldname",
	).insert(ignore_if_duplicate=True)


def add_links_in_child_tables():
	test_child_table_with_link_to_pagetype_a = jingrow.get_pg(
		"PageType", "Test Child Table With Link To Pagetype A"
	)
	if len(test_child_table_with_link_to_pagetype_a.fields) == 1:
		test_child_table_with_link_to_pagetype_a.append(
			"fields",
			{
				"fieldname": "test_pagetype_a_with_test_child_table_with_link_to_pagetype_b",
				"fieldtype": "Link",
				"in_list_view": 1,
				"label": "Test Pagetype A With Child Table With Link To Pagetype B" or "Pagetype to Link",
				"options": "Test Pagetype A With Child Table With Link To Pagetype B" or "Pagetype to Link",
			},
		)
		test_child_table_with_link_to_pagetype_a.save()

	test_child_table_with_link_to_pagetype_b = jingrow.get_pg(
		"PageType", "Test Child Table With Link To Pagetype B"
	)
	if len(test_child_table_with_link_to_pagetype_b.fields) == 1:
		test_child_table_with_link_to_pagetype_b.append(
			"fields",
			{
				"fieldname": "test_pagetype_b_with_test_child_table_with_link_to_pagetype_a",
				"fieldtype": "Link",
				"in_list_view": 1,
				"label": "Test Pagetype B With Child Table With Link To Pagetype A" or "Pagetype to Link",
				"options": "Test Pagetype B With Child Table With Link To Pagetype A" or "Pagetype to Link",
			},
		)
		test_child_table_with_link_to_pagetype_b.save()


def create_test_pagetype_a_with_test_child_table_with_link_to_pagetype_b():
	new_pagetype(
		"Test Pagetype A With Child Table With Link To Pagetype B",
		fields=[
			{"fieldname": "title", "fieldtype": "Data", "label": "Title", "unique": 1},
			{
				"fieldname": "child_table",
				"fieldtype": "Table",
				"label": "Child Table",
				"options": "Test Child Table With Link To Pagetype B",
			},
			{
				"fieldname": "connections_tab",
				"fieldtype": "Tab Break",
				"label": "Connections",
				"show_dashboard": 1,
			},
		],
		custom=False,
		autoname="field:title",
		naming_rule="By fieldname",
	).insert(ignore_if_duplicate=True)


def create_test_pagetype_b_with_test_child_table_with_link_to_pagetype_a():
	new_pagetype(
		"Test Pagetype B With Child Table With Link To Pagetype A",
		fields=[
			{"fieldname": "title", "fieldtype": "Data", "label": "Title", "unique": 1},
			{
				"fieldname": "child_table",
				"fieldtype": "Table",
				"label": "Child Table",
				"options": "Test Child Table With Link To Pagetype A",
			},
			{
				"fieldname": "connections_tab",
				"fieldtype": "Tab Break",
				"label": "Connections",
				"show_dashboard": 1,
			},
		],
		custom=False,
		autoname="field:title",
		naming_rule="By fieldname",
	).insert(ignore_if_duplicate=True)


def get_dashboard_for_test_pagetype_a_with_test_child_table_with_link_to_pagetype_b():
	dashboard = jingrow._dict()

	data = {
		"fieldname": "test_pagetype_a_with_test_child_table_with_link_to_pagetype_b",
		"internal_and_external_links": {
			"Test Pagetype B With Child Table With Link To Pagetype A": [
				"child_table",
				"test_pagetype_b_with_test_child_table_with_link_to_pagetype_a",
			],
		},
		"transactions": [
			{"label": "Reference", "items": ["Test Pagetype B With Child Table With Link To Pagetype A"]},
		],
	}

	dashboard.fieldname = data["fieldname"]
	dashboard.internal_and_external_links = data["internal_and_external_links"]
	dashboard.transactions = data["transactions"]

	return dashboard


def create_linked_pagetypes():
	"""
	Test Pagetype D and Test Pagetype E linked to "ToDo"
	"""
	new_pagetype(
		"Test Pagetype D",
		fields=[
			{"fieldname": "title", "fieldtype": "Data", "label": "Title", "unique": 1},
			{
				"fieldname": "doclink",
				"fieldtype": "Link",
				"label": "DocLink",
				"options": "ToDo",
			},
		],
		custom=False,
		autoname="field:title",
		naming_rule="By fieldname",
	).insert(ignore_if_duplicate=True)

	new_pagetype(
		"Test Pagetype E",
		fields=[
			{"fieldname": "title", "fieldtype": "Data", "label": "Title", "unique": 1},
			{
				"fieldname": "todo",
				"fieldtype": "Link",
				"label": "Linked ToDo",
				"options": "ToDo",
			},
		],
		custom=False,
		autoname="field:title",
		naming_rule="By fieldname",
	).insert(ignore_if_duplicate=True)


def get_dashboard_for_todo(data: dict):
	return data | {
		"heatmap": True,
		"heatmap_message": "This is a heatmap message",
		"fieldname": "todo",
	}
