import time

import jingrow
from dns.resolver import Resolver
from jingrow.utils import strip

from jcloud.api.server import plans
from jcloud.api.site import NAMESERVERS
from jcloud.runner import Ansible
from jcloud.utils import get_current_team


@jingrow.whitelist()
def new(server):
	server_details = jingrow._dict(server)

	team = get_current_team(get_pg=True)
	validate_team(team)

	proxy_server = get_proxy_server_for_cluster()

	return create_self_hosted_server(server_details, team, proxy_server)


def create_self_hosted_server(server_details, team, proxy_server):
	try:
		self_hosted_server = jingrow.new_pg(
			"Self Hosted Server",
			**{
				"ip": strip(server_details.get("app_public_ip", "")),
				"private_ip": strip(server_details.get("app_private_ip", "")),
				"mariadb_ip": strip(server_details.get("db_public_ip", "")),
				"mariadb_private_ip": strip(server_details.get("db_private_ip", "")),
				"title": server_details.title,
				"proxy_server": proxy_server,
				"proxy_created": True,
				"different_database_server": True,
				"team": team.name,
				"plan": server_details.plan["name"],
				"database_plan": server_details.plan["name"],
				"new_server": True,
			},
		).insert()
	except jingrow.DuplicateEntryError as e:
		# Exception return  tupple like ('Self Hosted Server', 'SHS-00018.cloud.jcloudonprem.com')
		server_name = e.args[1]
		return server_name

	return self_hosted_server.name


def validate_team(team):
	if not team:
		jingrow.throw("You must be part of a team to create a new server")

	if not team.enabled:
		jingrow.throw("You cannot create a new server because your account is disabled")

	if not team.self_hosted_servers_enabled:
		jingrow.throw(
			"You cannot create a new server because Hybrid Cloud is disabled for your account. Please contact support to enable it."
		)


def get_proxy_server_for_cluster(cluster=None):
	cluster = get_hybrid_cluster() if not cluster else cluster

	return jingrow.get_all("Proxy Server", {"cluster": cluster}, pluck="name")[0]


def get_hybrid_cluster():
	return jingrow.db.get_value("Cluster", {"hybrid": 1}, "name")


@jingrow.whitelist()
def sshkey():
	return jingrow.db.get_value("SSH Key", {"enabled": 1, "default": 1}, "public_key")


@jingrow.whitelist()
def verify(server):
	server_pg = jingrow.get_pg("Self Hosted Server", server)

	app_server_verified = verify_server("app", server_pg)
	db_server_verified = verify_server("db", server_pg)

	if app_server_verified and db_server_verified:
		server_pg.check_minimum_specs()

		server_pg.status = "Pending"
		server_pg.save()

		server_pg.reload()
		server_pg.create_database_server()

		server_pg.reload()
		server_pg.create_application_server()
		return True

	return False


def verify_server(server_type, server_pg):
	ping = Ansible(
		playbook="ping.yml",
		server=jingrow._dict(
			{
				"pagetype": "Self Hosted Server",
				"name": server_pg.name,
				"ssh_user": server_pg.ssh_user,
				"ssh_port": server_pg.ssh_port,
				"ip": server_pg.ip if server_type == "app" else server_pg.mariadb_ip,
			}
		),
	)
	result = ping.run()

	if result.status == "Success":
		server_pg.validate_private_ip(result.name, server_type=server_type)

		server_pg.fetch_system_specifications(result.name, server_type=server_type)
		server_pg.reload()

		return True

	return False


@jingrow.whitelist()
def setup(server):
	server_pg = jingrow.get_pg("Self Hosted Server", server)
	server_pg.start_setup = True
	server_pg.save()
	server_pg.setup_server()
	time.sleep(1)


@jingrow.whitelist()
def get_plans():
	server_plan = plans("Self Hosted Server")
	return server_plan


@jingrow.whitelist()
def check_dns(domain, ip):
	try:
		resolver = Resolver(configure=False)
		resolver.nameservers = NAMESERVERS
		domain_ip = resolver.query(domain.strip(), "A")[0].to_text()
		if domain_ip == ip:
			return True
	except Exception:
		return False
	return False


@jingrow.whitelist()
def options_for_new():
	return {"plans": get_plans(), "ssh_key": sshkey()}


@jingrow.whitelist()
def create_and_verify_selfhosted(server):
	self_hosted_server_name = new(server)

	if verify(self_hosted_server_name):
		setup(self_hosted_server_name)
		return jingrow.get_value("Self Hosted Server", self_hosted_server_name, "server")

	else:
		jingrow.throw(
			"Server verification failed. Please check the server details and try again."
		)
