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

from __future__ import annotations

import jingrow
from jingrow import _
from jingrow.rate_limiter import rate_limit


@jingrow.whitelist(allow_guest=True, methods=["POST"])
def sync_product_site_user(**data):
	"""
	Sync user info from product site

	Warning: Do not change the function name since it is used in production sites to sync user info
	"""
	import json

	headers = jingrow.request.headers
	site = headers.get("x-site")
	site_token = headers.get("x-site-token")

	if not jingrow.db.exists("Site", site):
		jingrow.throw("Invalid site")

	if not site_token:
		jingrow.throw("Invalid communication secret")

	site = jingrow.db.get_value("Site", site, ["saas_communication_secret", "name"], as_dict=True)

	if site.saas_communication_secret != site_token:
		jingrow.throw("Invalid token")

	user_info = data.get("user_info")

	if not user_info:
		jingrow.throw("No user info provided")

	if type(user_info) is str:
		user_info = json.loads(user_info)

	user_mail = user_info.get("email")
	enabled = user_info.get("enabled")
	if jingrow.db.exists("Site User", {"site": site.name, "user": user_mail}):
		user = jingrow.db.get_value(
			"Site User", {"site": site.name, "user": user_mail}, ["name", "enabled"], as_dict=True
		)
		if user.enabled != enabled:
			jingrow.db.set_value("Site User", user.name, "enabled", enabled)
	else:
		jingrow.get_pg(
			{
				"pagetype": "Site User",
				"site": site.name,
				"user": user_mail,
				"enabled": enabled,
			}
		).insert(ignore_permissions=True)


@jingrow.whitelist(allow_guest=True)
@rate_limit(limit=10, seconds=60)
def get_product_sites_of_user(user: str):
	"""
	Get all product sites of a user
	"""
	if not jingrow.db.exists("Site User", {"user": user}):
		return []

	session_id = jingrow.local.request.cookies.get("site_user_sid")
	if (
		not session_id
		or not isinstance(session_id, str)
		or not jingrow.db.exists("Site User Session", {"user": user, "session_id": session_id})
	) and (jingrow.session.user == "Guest"):
		return jingrow.throw("Invalid session")

	sites = jingrow.db.get_all(
		"Site User", filters={"user": user, "enabled": 1}, fields=["site"], pluck="site"
	)

	return jingrow.db.get_all(
		"Site",
		filters={"name": ["in", sites], "status": "Active"},
		fields=[
			"name",
			"label",
			"trial_end_date",
			"plan.plan_title as plan_title",
			"plan.price_usd as price_usd",
			"plan.price_cny as price_cny",
			"host_name",
		],
	)


@jingrow.whitelist(allow_guest=True)
@rate_limit(limit=5, seconds=60 * 5)
def send_otp(email: str):
	"""
	Send OTP to the user trying to login to the product site from /site-login page
	"""

	last_otp = jingrow.db.get_value("Site User Session", {"user": email}, "otp_generated_at")
	if last_otp and (jingrow.utils.now_datetime() - last_otp).seconds < 30:
		return jingrow.throw("Please wait for 30 seconds before sending the OTP again")

	session = jingrow.get_pg({"pagetype": "Site User Session", "user": email}).insert(ignore_permissions=True)
	return session.send_otp()


@jingrow.whitelist(allow_guest=True)
@rate_limit(limit=5, seconds=60 * 60)
def verify_otp(email: str, otp: str):
	"""
	Verify OTP
	"""

	session = jingrow.db.get_value(
		"Site User Session", {"user": email}, ["name", "session_id", "otp", "otp_generated_at"], as_dict=True
	)
	if not session:
		return jingrow.throw("Invalid session")

	if not session.otp:
		return jingrow.throw("OTP is not set")

	if (jingrow.utils.now_datetime() - session.otp_generated_at).seconds > 300:
		return jingrow.throw("OTP is expired")

	if session.otp != otp:
		return jingrow.throw("Invalid OTP")

	jingrow.db.set_value("Site User Session", session.name, {"otp": None, "verified": 1})

	five_days_in_seconds = 5 * 24 * 60 * 60
	return jingrow.local.cookie_manager.set_cookie(
		"site_user_sid", session.session_id, max_age=five_days_in_seconds, httponly=True
	)


@jingrow.whitelist(allow_guest=True)
@rate_limit(limit=5, seconds=60)
def login_to_site(email: str, site: str):
	"""
	Login to the product site
	"""
	session_id = jingrow.local.request.cookies.get("site_user_sid")
	if not session_id or not isinstance(session_id, str):
		if jingrow.session.user == "Guest":
			return jingrow.throw("Invalid session")
		jingrow.get_pg({"pagetype": "Site User Session", "user": email}).insert(ignore_permissions=True)

	site_user_name = jingrow.db.get_value("Site User", {"user": email, "site": site}, "name")
	if not site_user_name:
		return jingrow.throw(f"User {email} not found in site {site}")
	site_user = jingrow.get_pg("Site User", site_user_name)
	if not site_user.enabled:
		jingrow.throw(_(f"User is disabled for the site {site}"))

	return site_user.login_to_site()


@jingrow.whitelist(allow_guest=True)
@rate_limit(limit=5, seconds=60)
def check_session_id():
	"""
	Check if the session id is valid
	"""

	session_id = jingrow.local.request.cookies.get("site_user_sid")
	if not session_id or not isinstance(session_id, str):
		return False

	session_user = jingrow.db.get_value("Site User Session", {"session_id": session_id}, "user")
	if not session_user:
		return False

	return session_user
