# Copyright (c) 2019, JINGROW
# See license.txt

from __future__ import annotations

import typing
import unittest
from unittest.mock import Mock, patch

import jingrow
from jingrow.model.naming import make_autoname

from jcloud.jcloud.pagetype.database_server.test_database_server import (
	create_test_database_server,
)
from jcloud.jcloud.pagetype.jcloud_settings.test_jcloud_settings import (
	create_test_jcloud_settings,
)
from jcloud.jcloud.pagetype.proxy_server.test_proxy_server import create_test_proxy_server
from jcloud.jcloud.pagetype.server.server import BaseServer
from jcloud.jcloud.pagetype.server_plan.test_server_plan import create_test_server_plan
from jcloud.jcloud.pagetype.team.test_team import create_test_team
from jcloud.jcloud.pagetype.virtual_machine.test_virtual_machine import create_test_virtual_machine

if typing.TYPE_CHECKING:
	from jcloud.jcloud.pagetype.server.server import Server


@patch.object(BaseServer, "after_insert", new=Mock())
def create_test_server(
	proxy_server: str | None = None,
	database_server: str | None = None,
	cluster: str = "Default",
	plan: str | None = None,
	team: str | None = None,
	public: bool = False,
) -> "Server":
	"""Create test Server pg."""
	if not proxy_server:
		proxy_server = create_test_proxy_server().name
	if not database_server:
		database_server = create_test_database_server().name
	if not team:
		team = create_test_team().name
	server = jingrow.get_pg(
		{
			"pagetype": "Server",
			"status": "Active",
			"proxy_server": proxy_server,
			"database_server": database_server,
			"ip": jingrow.mock("ipv4"),
			"private_ip": jingrow.mock("ipv4_private"),
			"domain": "fc.dev",
			"hostname": make_autoname("f-.####"),
			"cluster": cluster,
			"new_worker_allocation": True,
			"ram": 16000,
			"team": team,
			"plan": plan,
			"public": public,
			"virtual_machine": create_test_virtual_machine(),
		}
	).insert()
	server.reload()
	return server


@patch.object(BaseServer, "after_insert", new=Mock())
class TestServer(unittest.TestCase):
	def test_create_generic_server(self):
		create_test_jcloud_settings()
		proxy_server = create_test_proxy_server()
		database_server = create_test_database_server()

		server = jingrow.get_pg(
			{
				"pagetype": "Server",
				"hostname": jingrow.mock("domain_word"),
				"domain": "fc.dev",
				"ip": jingrow.mock("ipv4"),
				"private_ip": jingrow.mock("ipv4_private"),
				"agent_password": jingrow.mock("password"),
				"proxy_server": proxy_server.name,
				"database_server": database_server.name,
			}
		)
		server.insert()
		self.assertEqual(server.cluster, "Default")
		self.assertEqual(server.name, f"{server.hostname}.{server.domain}")

	def test_set_agent_password(self):
		create_test_jcloud_settings()
		proxy_server = create_test_proxy_server()
		database_server = create_test_database_server()

		server = jingrow.get_pg(
			{
				"pagetype": "Server",
				"hostname": jingrow.mock("domain_word"),
				"domain": "fc.dev",
				"ip": jingrow.mock("ipv4"),
				"private_ip": jingrow.mock("ipv4_private"),
				"proxy_server": proxy_server.name,
				"database_server": database_server.name,
			}
		)
		server.insert()
		self.assertEqual(len(server.get_password("agent_password")), 32)

	def test_subscription_creation_on_server_creation(self):
		create_test_jcloud_settings()
		server_plan = create_test_server_plan()
		server = create_test_server(plan=server_plan.name)
		server.create_subscription(server.plan)
		subscription = jingrow.get_pg(
			"Subscription",
			{"document_type": "Server", "document_name": server.name, "enabled": 1},
		)
		self.assertEqual(server.team, subscription.team)
		self.assertEqual(server.plan, subscription.plan)

	def test_new_subscription_on_server_team_update(self):
		create_test_jcloud_settings()
		server_plan = create_test_server_plan()
		server = create_test_server(plan=server_plan.name)
		server.create_subscription(server.plan)
		subscription = jingrow.get_pg(
			"Subscription",
			{"document_type": "Server", "document_name": server.name, "enabled": 1},
		)
		self.assertEqual(server.team, subscription.team)
		self.assertEqual(server.plan, subscription.plan)

		# update server team
		team2 = create_test_team()
		server.team = team2.name
		server.save()
		subscription = jingrow.get_pg(
			"Subscription",
			{"document_type": "Server", "document_name": server.name, "enabled": 1},
		)
		self.assertEqual(server.team, subscription.team)
		self.assertEqual(server.plan, subscription.plan)

	def tearDown(self):
		jingrow.db.rollback()
