# Copyright (c) 2020, JINGROW
# For license information, please see license.txt
from __future__ import annotations

from itertools import groupby
import urllib.parse
import json
import segno
import io
import base64
import jingrow
from jingrow import _  # Import this for translation functionality
from jingrow.core.utils import find
from jingrow.utils import fmt_money, get_request_site_address, getdate, add_months
import random
from datetime import datetime

from jcloud.api.regional_payments.mpesa.utils import (
	create_invoice_partner_site,
	create_payment_partner_transaction,
	fetch_param_value,
	get_details_from_request_log,
	get_mpesa_setup_for_team,
	get_payment_gateway,
	sanitize_mobile_number,
	update_tax_id_or_phone_no,
)
from jcloud.jcloud.pagetype.mpesa_setup.mpesa_connector import MpesaConnector
from jcloud.jcloud.pagetype.team.team import (
	has_unsettled_invoices,
)
from jcloud.utils import get_current_team
from jcloud.utils.billing import (
	GSTIN_FORMAT,
	clear_setup_intent,
	get_publishable_key,
	get_razorpay_client,
	get_setup_intent,
	get_stripe,
	make_formatted_pg,
	states_with_tin,
	validate_gstin_check_digit,
)
from jcloud.utils.mpesa_utils import create_mpesa_request_log
from jcloud.api.payment.wechatpay import WeChatPayAPI
from jcloud.api.payment.alipay import AlipayAPI
from jcloud.api.payment.paypal import PayPalAPI

@jingrow.whitelist()
def get_publishable_key_and_setup_intent():
	team = get_current_team()
	return {
		"publishable_key": get_publishable_key(),
		"setup_intent": get_setup_intent(team),
	}


@jingrow.whitelist()
def upcoming_invoice():
	team = get_current_team(True)
	invoice = team.get_upcoming_invoice()

	if invoice:
		upcoming_invoice = invoice.as_dict()
		upcoming_invoice.formatted = make_formatted_pg(invoice, ["Currency"])
	else:
		upcoming_invoice = None

	return {
		"upcoming_invoice": upcoming_invoice,
		"available_credits": fmt_money(team.get_balance(), 2, team.currency),
	}


@jingrow.whitelist()
def get_balance_credit():
	team = get_current_team(True)
	return team.get_balance()


@jingrow.whitelist()
def past_invoices():
	return get_current_team(True).get_past_invoices()


@jingrow.whitelist()
def invoices_and_payments():
	team = get_current_team(True)
	return team.get_past_invoices()


@jingrow.whitelist()
def refresh_invoice_link(invoice):
	pg = jingrow.get_pg("Invoice", invoice)
	return pg.refresh_stripe_payment_link()


@jingrow.whitelist()
def balances():
	team = get_current_team()
	has_bought_credits = jingrow.db.get_all(
		"Balance Transaction",
		filters={
			"source": ("in", ("Prepaid Credits", "Transferred Credits", "Free Credits")),
			"team": team,
			"pagestatus": 1,
			"type": ("!=", "Partnership Fee"),
		},
		limit=1,
	)
	if not has_bought_credits:
		return []

	bt = jingrow.qb.PageType("Balance Transaction")
	inv = jingrow.qb.PageType("Invoice")
	query = (
		jingrow.qb.from_(bt)
		.left_join(inv)
		.on(bt.invoice == inv.name)
		.select(
			bt.name,
			bt.creation,
			bt.amount,
			bt.currency,
			bt.source,
			bt.type,
			bt.ending_balance,
			bt.description,
			inv.period_start,
		)
		.where((bt.pagestatus == 1) & (bt.team == team))
		.orderby(bt.creation, order=jingrow.qb.desc)
	)

	data = query.run(as_dict=True)
	for d in data:
		d.formatted = dict(
			amount=fmt_money(d.amount, 2, d.currency),
			ending_balance=fmt_money(d.ending_balance, 2, d.currency),
		)

		if d.period_start:
			d.formatted["invoice_for"] = d.period_start.strftime("%B %Y")
	return data


def get_processed_balance_transactions(transactions: list[dict]):
	"""Cleans up transactions and adjusts ending balances accordingly"""

	cleaned_up_transations = get_cleaned_up_transactions(transactions)
	processed_balance_transactions = []
	for bt in reversed(cleaned_up_transations):
		if is_added_credits_bt(bt) and len(processed_balance_transactions) < 1:
			processed_balance_transactions.append(bt)
		elif is_added_credits_bt(bt):
			bt.ending_balance += processed_balance_transactions[
				-1
			].ending_balance  # Adjust the ending balance
			processed_balance_transactions.append(bt)
		elif bt.type == "Applied To Invoice":
			processed_balance_transactions.append(bt)

	return list(reversed(processed_balance_transactions))


def get_cleaned_up_transactions(transactions: list[dict]):
	"""Only picks Balance transactions that the users care about"""

	cleaned_up_transations = []
	for bt in transactions:
		if is_added_credits_bt(bt):
			cleaned_up_transations.append(bt)
			continue

		if bt.type == "Applied To Invoice" and not find(
			cleaned_up_transations, lambda x: x.invoice == bt.invoice
		):
			cleaned_up_transations.append(bt)
			continue
	return cleaned_up_transations


def is_added_credits_bt(bt):
	"""Returns `true` if credits were added and not some reverse transaction"""
	if not (
		bt.type == "Adjustment"
		and bt.source
		in (
			"Prepaid Credits",
			"Free Credits",
			"Transferred Credits",
		)  # Might need to re-think this
	):
		return False

	# Is not a reverse of a previous balance transaction
	bt.description = bt.description or ""
	return not bt.description.startswith("Reverse")


@jingrow.whitelist()
def details():
	team = get_current_team(True)
	address = None
	if team.billing_address:
		address = jingrow.get_pg("Address", team.billing_address)
		address_parts = [
			address.address_line1,
			address.city,
			address.state,
			address.country,
			address.pincode,
		]
		billing_address = ", ".join([d for d in address_parts if d])
	else:
		billing_address = ""

	return {
		"billing_name": team.billing_name,
		"billing_address": billing_address,
		"gstin": address.gstin if address else None,
	}


@jingrow.whitelist()
def get_customer_details(team):
	"""This method is called by jingrow.com for creating Customer and Address"""
	team_pg = jingrow.db.get_value("Team", team, "*")
	return {
		"team": team_pg,
		"address": jingrow.get_pg("Address", team_pg.billing_address),
	}


@jingrow.whitelist()
def create_payment_intent_for_micro_debit(payment_method_name):
	team = get_current_team(True)
	stripe = get_stripe()

	micro_debit_charge_field = (
		"micro_debit_charge_usd" if team.currency == "USD" else "micro_debit_charge_cny"
	)
	amount = jingrow.db.get_single_value("Jcloud Settings", micro_debit_charge_field)

	intent = stripe.PaymentIntent.create(
		amount=int(amount * 100),
		currency=team.currency.lower(),
		customer=team.stripe_customer_id,
		description="Micro-Debit Card Test Charge",
		metadata={
			"payment_for": "micro_debit_test_charge",
			"payment_method_name": payment_method_name,
		},
	)
	return {"client_secret": intent["client_secret"]}


@jingrow.whitelist()
def create_payment_intent_for_partnership_fees():
	team = get_current_team(True)
	jcloud_settings = jingrow.get_cached_pg("Jcloud Settings")
	metadata = {"payment_for": "partnership_fee"}
	fee_amount = jcloud_settings.partnership_fee_usd

	if team.currency == "CNY":
		fee_amount = jcloud_settings.partnership_fee_cny
		gst_amount = fee_amount * jcloud_settings.gst_percentage
		fee_amount += gst_amount
		metadata.update({"gst": round(gst_amount, 2)})

	stripe = get_stripe()
	intent = stripe.PaymentIntent.create(
		amount=int(fee_amount * 100),
		currency=team.currency.lower(),
		customer=team.stripe_customer_id,
		description="Partnership Fee",
		metadata=metadata,
	)
	return {
		"client_secret": intent["client_secret"],
		"publishable_key": get_publishable_key(),
	}


@jingrow.whitelist()
def create_payment_intent_for_buying_credits(amount):
	team = get_current_team(True)
	metadata = {"payment_for": "prepaid_credits"}
	total_unpaid = total_unpaid_amount()

	if amount < total_unpaid and not team.jerp_partner:
		jingrow.throw(f"Amount {amount} is less than the total unpaid amount {total_unpaid}.")

	if team.currency == "CNY":
		gst_amount = amount * jingrow.db.get_single_value("Jcloud Settings", "gst_percentage")
		amount += gst_amount
		metadata.update({"gst": round(gst_amount, 2)})

	amount = round(amount, 2)
	stripe = get_stripe()
	intent = stripe.PaymentIntent.create(
		amount=int(amount * 100),
		currency=team.currency.lower(),
		customer=team.stripe_customer_id,
		description="Prepaid Credits",
		metadata=metadata,
	)
	return {
		"client_secret": intent["client_secret"],
		"publishable_key": get_publishable_key(),
	}


@jingrow.whitelist()
def create_payment_intent_for_prepaid_app(amount, metadata):
	stripe = get_stripe()
	team = get_current_team(True)
	payment_method = jingrow.get_value(
		"Stripe Payment Method", team.default_payment_method, "stripe_payment_method_id"
	)
	try:
		if not payment_method:
			intent = stripe.PaymentIntent.create(
				amount=amount * 100,
				currency=team.currency.lower(),
				customer=team.stripe_customer_id,
				description="Prepaid App Purchase",
				metadata=metadata,
			)
		else:
			intent = stripe.PaymentIntent.create(
				amount=amount * 100,
				currency=team.currency.lower(),
				customer=team.stripe_customer_id,
				description="Prepaid App Purchase",
				off_session=True,
				confirm=True,
				metadata=metadata,
				payment_method=payment_method,
				payment_method_options={"card": {"request_three_d_secure": "any"}},
			)

		return {
			"payment_method": payment_method,
			"client_secret": intent["client_secret"],
			"publishable_key": get_publishable_key(),
		}
	except stripe.error.CardError as e:
		err = e.error
		if err.code == "authentication_required":
			# Bring the customer back on-session to authenticate the purchase
			return {
				"error": "authentication_required",
				"payment_method": err.payment_method.id,
				"amount": amount,
				"card": err.payment_method.card,
				"publishable_key": get_publishable_key(),
				"client_secret": err.payment_intent.client_secret,
			}
		if err.code:
			# The card was declined for other reasons (e.g. insufficient funds)
			# Bring the customer back on-session to ask them for a new payment method
			return {
				"error": err.code,
				"payment_method": err.payment_method.id,
				"publishable_key": get_publishable_key(),
				"client_secret": err.payment_intent.client_secret,
			}


@jingrow.whitelist()
def get_payment_methods():
	team = get_current_team()
	return jingrow.get_pg("Team", team).get_payment_methods()


@jingrow.whitelist()
def set_as_default(name):
	payment_method = jingrow.get_pg("Stripe Payment Method", {"name": name, "team": get_current_team()})
	payment_method.set_default()


@jingrow.whitelist()
def remove_payment_method(name):
	team = get_current_team()
	payment_method_count = jingrow.db.count("Stripe Payment Method", {"team": team})

	if has_unsettled_invoices(team) and payment_method_count == 1:
		return "Unpaid Invoices"

	payment_method = jingrow.get_pg("Stripe Payment Method", {"name": name, "team": team})
	payment_method.delete()
	return None


@jingrow.whitelist()
def finalize_invoices():
	unsettled_invoices = jingrow.get_all(
		"Invoice",
		{"team": get_current_team(), "status": ("in", ("Draft", "Unpaid"))},
		pluck="name",
	)

	for inv in unsettled_invoices:
		inv_pg = jingrow.get_pg("Invoice", inv)
		inv_pg.finalize_invoice()


@jingrow.whitelist()
def unpaid_invoices():
	team = get_current_team()
	return jingrow.db.get_all(
		"Invoice",
		{
			"team": team,
			"status": ("in", ["Draft", "Unpaid", "Invoice Created"]),
			"type": "Subscription",
		},
		["name", "status", "period_end", "currency", "amount_due", "total"],
		order_by="creation asc",
	)


@jingrow.whitelist()
def get_unpaid_invoices():
	team = get_current_team()
	unpaid_invoices = jingrow.db.get_all(
		"Invoice",
		{
			"team": team,
			"status": "Unpaid",
			"type": "Subscription",
		},
		["name", "status", "period_end", "currency", "amount_due", "total"],
		order_by="creation asc",
	)

	if len(unpaid_invoices) == 1:
		return jingrow.get_pg("Invoice", unpaid_invoices[0].name)
	return unpaid_invoices


@jingrow.whitelist()
def change_payment_mode(mode):
	team = get_current_team(get_pg=True)

	team.payment_mode = mode
	if team.partner_email and mode == "Paid By Partner" and not team.billing_team:
		team.billing_team = jingrow.db.get_value(
			"Team",
			{"enabled": 1, "jerp_partner": 1, "partner_email": team.partner_email},
			"name",
		)
	if team.billing_team and mode != "Paid By Partner":
		team.billing_team = ""
	team.save()
	return None


@jingrow.whitelist()
def prepaid_credits_via_onboarding():
	"""When prepaid credits are bought, the balance is not immediately reflected.
	This method will check balance every second and then set payment_mode"""
	from time import sleep

	team = get_current_team(get_pg=True)

	seconds = 0
	# block until balance is updated
	while team.get_balance() == 0 or seconds > 20:
		seconds += 1
		sleep(1)
		jingrow.db.rollback()

	team.payment_mode = "Prepaid Credits"
	team.save()


@jingrow.whitelist()
def get_invoice_usage(invoice):
	team = get_current_team()
	# apply team filter for safety
	pg = jingrow.get_pg("Invoice", {"name": invoice, "team": team})
	out = pg.as_dict()
	# a dict with formatted currency values for display
	out.formatted = make_formatted_pg(pg)
	out.invoice_pdf = pg.invoice_pdf or (pg.currency == "USD" and pg.get_pdf())
	return out


@jingrow.whitelist()
def get_summary():
	team = get_current_team()
	invoices = jingrow.get_all(
		"Invoice",
		filters={"team": team, "status": ("in", ["Paid", "Unpaid"])},
		fields=[
			"name",
			"status",
			"period_end",
			"payment_mode",
			"type",
			"currency",
			"amount_paid",
		],
		order_by="creation desc",
	)

	invoice_names = [x.name for x in invoices]
	grouped_invoice_items = get_grouped_invoice_items(invoice_names)

	for invoice in invoices:
		invoice.items = grouped_invoice_items.get(invoice.name, [])

	return invoices


def get_grouped_invoice_items(invoices: list[str]) -> dict:
	"""Takes a list of invoices (invoice names) and returns a dict of the form:
	{ "<invoice_name1>": [<invoice_items>], "<invoice_name2>": [<invoice_items>], }
	"""
	invoice_items = jingrow.get_all(
		"Invoice Item",
		filters={"parent": ("in", invoices)},
		fields=[
			"amount",
			"document_name AS name",
			"document_type AS type",
			"parent",
			"quantity",
			"rate",
			"plan",
		],
	)

	grouped_items = groupby(invoice_items, key=lambda x: x["parent"])
	invoice_items_map = {}
	for invoice_name, items in grouped_items:
		invoice_items_map[invoice_name] = list(items)

	return invoice_items_map


@jingrow.whitelist()
def after_card_add():
	clear_setup_intent()


@jingrow.whitelist()
def setup_intent_success(setup_intent, address=None):
	setup_intent = jingrow._dict(setup_intent)

	# refetching the setup intent to get mandate_id from stripe
	stripe = get_stripe()
	setup_intent = stripe.SetupIntent.retrieve(setup_intent.id)

	team = get_current_team(True)
	clear_setup_intent()
	mandate_reference = setup_intent.payment_method_options.card.mandate_options.reference
	payment_method = team.create_payment_method(
		setup_intent.payment_method,
		setup_intent.id,
		setup_intent.mandate,
		mandate_reference,
		set_default=True,
	)
	if address:
		address = jingrow._dict(address)
		team.update_billing_details(address)

	return {"payment_method_name": payment_method.name}


@jingrow.whitelist()
def validate_gst(address, method=None):
	# 保留函数以维持代码结构
	return


@jingrow.whitelist()
def get_latest_unpaid_invoice():
	team = get_current_team()
	unpaid_invoices = jingrow.get_all(
		"Invoice",
		{"team": team, "status": "Unpaid", "payment_attempt_count": (">", 0)},
		pluck="name",
		order_by="creation desc",
		limit=1,
	)

	if unpaid_invoices:
		unpaid_invoice = jingrow.db.get_value(
			"Invoice",
			unpaid_invoices[0],
			["amount_due", "payment_mode", "amount_due", "currency"],
			as_dict=True,
		)
		if unpaid_invoice.payment_mode == "Prepaid Credits" and team_has_balance_for_invoice(unpaid_invoice):
			return None

		return unpaid_invoice
	return None


def team_has_balance_for_invoice(prepaid_mode_invoice):
	team = get_current_team(get_pg=True)
	return team.get_balance() >= prepaid_mode_invoice.amount_due


@jingrow.whitelist()
def create_razorpay_order(amount, type=None):
	client = get_razorpay_client()
	team = get_current_team(get_pg=True)

	if team.currency == "CNY":
		gst_amount = amount * jingrow.db.get_single_value("Jcloud Settings", "gst_percentage")
		amount += gst_amount

	amount = round(amount, 2)
	data = {
		"amount": int(amount * 100),
		"currency": team.currency,
		"notes": {
			"Description": "Order for Jingrow Prepaid Credits",
			"Team (Jingrow ID)": team.name,
			"gst": gst_amount if team.currency == "CNY" else 0,
		},
	}
	if type and type == "Partnership Fee":
		data.get("notes").update({"Type": type})
	order = client.order.create(data=data)

	payment_record = jingrow.get_pg(
		{"pagetype": "Razorpay Payment Record", "order_id": order.get("id"), "team": team.name, "type": type}
	).insert(ignore_permissions=True)

	return {
		"order_id": order.get("id"),
		"key_id": client.auth[0],
		"payment_record": payment_record.name,
	}


@jingrow.whitelist()
def handle_razorpay_payment_success(response):
	client = get_razorpay_client()
	client.utility.verify_payment_signature(response)

	payment_record = jingrow.get_pg(
		"Razorpay Payment Record",
		{"order_id": response.get("razorpay_order_id")},
		for_update=True,
	)
	payment_record.update(
		{
			"payment_id": response.get("razorpay_payment_id"),
			"signature": response.get("razorpay_signature"),
			"status": "Captured",
		}
	)
	payment_record.save(ignore_permissions=True)


@jingrow.whitelist()
def handle_razorpay_payment_failed(response):
	payment_record = jingrow.get_pg(
		"Razorpay Payment Record",
		{"order_id": response["error"]["metadata"].get("order_id")},
		for_update=True,
	)

	payment_record.status = "Failed"
	payment_record.failure_reason = response["error"]["description"]
	payment_record.save(ignore_permissions=True)


@jingrow.whitelist()
def total_unpaid_amount():
	team = get_current_team(get_pg=True)
	balance = team.get_balance()
	negative_balance = -1 * balance if balance < 0 else 0

	return (
		jingrow.get_all(
			"Invoice",
			{"status": "Unpaid", "team": team.name, "type": "Subscription", "pagestatus": ("!=", 2)},
			["sum(amount_due) as total"],
			pluck="total",
		)[0]
		or 0
	) + negative_balance


# Mpesa integrations, mpesa exjcloud
"""Send stk push to the user"""


def generate_stk_push(**kwargs):
	"""Generate stk push by making a API call to the stk push API."""
	args = jingrow._dict(kwargs)
	partner_value = args.partner

	# Fetch the team document based on the extracted partner value
	partner = jingrow.get_all("Team", filters={"user": partner_value, "jerp_partner": 1}, pluck="name")
	if not partner:
		jingrow.throw(_(f"Partner team {partner_value} not found"), title=_("Mpesa Exjcloud Error"))

	# Get Mpesa settings for the partner's team
	mpesa_setup = get_mpesa_setup_for_team(partner[0])
	try:
		callback_url = (
			get_request_site_address(True) + "/api/action/jcloud.api.billing.verify_m_pesa_transaction"
		)
		env = "production" if not mpesa_setup.sandbox else "sandbox"
		# for sandbox, business shortcode is same as till number
		business_shortcode = (
			mpesa_setup.business_shortcode if env == "production" else mpesa_setup.till_number
		)
		connector = MpesaConnector(
			env=env,
			app_key=mpesa_setup.consumer_key,
			app_secret=mpesa_setup.get_password("consumer_secret"),
		)

		mobile_number = sanitize_mobile_number(args.sender)
		response = connector.stk_push(
			business_shortcode=business_shortcode,
			amount=args.amount_with_tax,
			passcode=mpesa_setup.get_password("pass_key"),
			callback_url=callback_url,
			reference_code=mpesa_setup.till_number,
			phone_number=mobile_number,
			description="Jingrow Payment",
		)
		return response  # noqa: RET504
	except Exception as e:
		jingrow.log_error(f"Mpesa Exjcloud Transaction Error")
		jingrow.throw(
			_("Issue detected with Mpesa configuration, check the error logs for more details"),
			title=_("Mpesa Exjcloud Error"),
		)


@jingrow.whitelist(allow_guest=True)
def verify_m_pesa_transaction(**kwargs):
	"""Verify the transaction result received via callback from STK."""
	transaction_response, request_id = parse_transaction_response(kwargs)
	status = handle_transaction_result(transaction_response, request_id)

	return {"status": status, "ResultDesc": transaction_response.get("ResultDesc")}


def parse_transaction_response(kwargs):
	"""Parse and validate the transaction response."""

	if "Body" not in kwargs or "stkCallback" not in kwargs["Body"]:
		jingrow.log_error(title="Invalid transaction response format", message=kwargs)
		jingrow.throw(_("Invalid transaction response format"))

	transaction_response = jingrow._dict(kwargs["Body"]["stkCallback"])
	checkout_id = getattr(transaction_response, "CheckoutRequestID", "")
	if not isinstance(checkout_id, str):
		jingrow.throw(_("Invalid Checkout Request ID"))

	return transaction_response, checkout_id


def handle_transaction_result(transaction_response, integration_request):
	"""Handle the logic based on ResultCode in the transaction response."""

	result_code = transaction_response.get("ResultCode")
	status = None

	if result_code == 0:
		try:
			status = "Completed"
			create_mpesa_request_log(
				transaction_response, "Host", "Mpesa Exjcloud", integration_request, None, status
			)

			create_mpesa_payment_record(transaction_response)
		except Exception as e:
			status = "Failed"
			create_mpesa_request_log(
				transaction_response, "Host", "Mpesa Exjcloud", integration_request, None, status
			)

	elif result_code == 1037:  # User unreachable (Phone off or timeout)
		status = "Failed"
		create_mpesa_request_log(
			transaction_response, "Host", "Mpesa Exjcloud", integration_request, None, status
		)

	elif result_code == 1032:  # User cancelled the request
		status = "Cancelled"
		create_mpesa_request_log(
			transaction_response, "Host", "Mpesa Exjcloud", integration_request, None, status
		)

	else:  # Other failure codes
		status = "Failed"
		create_mpesa_request_log(
			transaction_response, "Host", "Mpesa Exjcloud", integration_request, None, status
		)
	return status


@jingrow.whitelist()
def request_for_payment(**kwargs):
	"""request for payments"""
	team = get_current_team()

	kwargs.setdefault("team", team)
	args = jingrow._dict(kwargs)
	update_tax_id_or_phone_no(team, args.tax_id, args.phone_number)

	amount = args.request_amount
	args.request_amount = jingrow.utils.rounded(amount, 2)
	response = jingrow._dict(generate_stk_push(**args))
	handle_api_mpesa_response("CheckoutRequestID", args, response)

	return response


def handle_api_mpesa_response(global_id, request_dict, response):
	"""Response received from API calls returns a global identifier for each transaction, this code is returned during the callback."""
	# check error response
	if response.requestId:
		req_name = response.requestId
		error = response
	else:
		# global checkout id used as request name
		req_name = getattr(response, global_id)
		error = None

	create_mpesa_request_log(request_dict, "Host", "Mpesa Exjcloud", req_name, error, output=response)

	if error:
		jingrow.throw(_(response.errorMessage), title=_("Transaction Error"))


def create_mpesa_payment_record(transaction_response):
	"""Create a new entry in the Mpesa Payment Record for a successful transaction."""
	item_response = transaction_response.get("CallbackMetadata", {}).get("Item", [])
	mpesa_receipt_number = fetch_param_value(item_response, "MpesaReceiptNumber", "Name")
	transaction_time = fetch_param_value(item_response, "TransactionDate", "Name")
	phone_number = fetch_param_value(item_response, "PhoneNumber", "Name")
	transaction_id = transaction_response.get("CheckoutRequestID")
	amount = fetch_param_value(item_response, "Amount", "Name")
	merchant_request_id = transaction_response.get("MerchantRequestID")
	info = get_details_from_request_log(transaction_id)
	gateway_name = get_payment_gateway(info.partner)
	# Create a new entry in M-Pesa Payment Record
	data = {
		"transaction_id": transaction_id,
		"amount": amount,
		"team": jingrow.get_value("Team", info.team, "user"),
		"default_currency": "KES",
		"rate": info.requested_amount,
	}
	mpesa_invoice, invoice_name = create_invoice_partner_site(data, gateway_name)
	payment_record = jingrow.get_pg(
		{
			"pagetype": "Mpesa Payment Record",
			"transaction_id": transaction_id,
			"transaction_time": parse_datetime(transaction_time),
			"transaction_type": "Mpesa Exjcloud",
			"team": info.team,
			"phone_number": str(phone_number),
			"amount": info.requested_amount,
			"grand_total": amount,
			"merchant_request_id": merchant_request_id,
			"payment_partner": info.partner,
			"amount_usd": info.amount_usd,
			"exchange_rate": info.exchange_rate,
			"local_invoice": mpesa_invoice,
			"mpesa_receipt_number": mpesa_receipt_number,
		}
	)
	payment_record.insert(ignore_permissions=True)
	payment_record.submit()
	"""create payment partner transaction which will then create balance transaction"""
	create_payment_partner_transaction(
		info.team, info.partner, info.exchange_rate, info.amount_usd, info.requested_amount, gateway_name
	)
	mpesa_details = {
		"mpesa_receipt_number": mpesa_receipt_number,
		"mpesa_merchant_id": merchant_request_id,
		"mpesa_payment_record": payment_record.name,
		"mpesa_request_id": transaction_id,
		"mpesa_invoice": invoice_name,
	}
	create_balance_transaction_and_invoice(info.team, info.amount_usd, mpesa_details)

	jingrow.msgprint(_("Mpesa Payment Record entry created successfully"))


def create_balance_transaction_and_invoice(team, amount, mpesa_details):
	balance_transaction = jingrow.get_pg(
		pagetype="Balance Transaction",
		team=team,
		source="Prepaid Credits",
		type="Adjustment",
		amount=amount,
		description=mpesa_details.get("mpesa_payment_record"),
		paid_via_local_pg=1,
	)
	balance_transaction.insert(ignore_permissions=True)
	balance_transaction.submit()

	invoice = jingrow.get_pg(
		pagetype="Invoice",
		team=team,
		type="Prepaid Credits",
		status="Paid",
		total=amount,
		amount_due=amount,
		amount_paid=amount,
		amount_due_with_tax=amount,
		due_date=jingrow.utils.nowdate(),
		mpesa_merchant_id=mpesa_details.get("mpesa_merchant_id", ""),
		mpesa_receipt_number=mpesa_details.get("mpesa_receipt_number", ""),
		mpesa_request_id=mpesa_details.get("mpesa_request_id", ""),
		mpesa_payment_record=mpesa_details.get("mpesa_payment_record", ""),
		mpesa_invoice=mpesa_details.get("mpesa_invoice", ""),
	)
	invoice.append(
		"items",
		{
			"description": "Prepaid Credits",
			"document_type": "Balance Transaction",
			"document_name": balance_transaction.name,
			"quantity": 1,
			"rate": amount,
		},
	)
	invoice.insert(ignore_permissions=True)
	invoice.submit()


def parse_datetime(date):
	from datetime import datetime

	return datetime.strptime(str(date), "%Y%m%d%H%M%S")

@jingrow.whitelist(allow_guest=True)
def handle_alipay_notification():
    """处理支付宝支付通知回调"""
    try:
        # 获取支付宝通知数据
        alipay_data = jingrow.request.form.to_dict()
        
        # 获取必要参数
        order_id = alipay_data.get("out_trade_no")
        trade_no = alipay_data.get("trade_no")
        trade_status = alipay_data.get("trade_status")
        team_name = urllib.parse.unquote(alipay_data.get("passback_params", ""))
        
        # 检查订单号是否存在
        if not order_id:
            jingrow.log_error("订单号为空", "支付宝错误")
            return "fail"
        
        # 查找支付记录
        payment_record = jingrow.db.get_value(
            "Order", 
            {"order_id": order_id}, 
            ["name", "total_amount", "status", "team"],
            as_dict=True
        )
        
        if not payment_record:
            jingrow.log_error(f"未找到支付记录: {order_id}", "支付宝错误")
            return "fail"
        
        # 检查记录状态，避免重复处理
        if payment_record.status == "交易成功":
            return "success"
        
        # 只有交易成功时才更新状态
        if trade_status == "TRADE_SUCCESS":           
            # 更新订单记录状态
            jingrow.db.set_value(
                "Order", 
                payment_record.name,
                {
                    "status": "已支付",
                    "trade_no": trade_no,
                    "payment_method": "支付宝"
                }
            )
            
            # 执行支付完成后的业务逻辑
            handle_order_payment_complete(order_id)
                       
            # 立即提交数据库事务
            jingrow.db.commit()           
            
            return "success"
        
        return "success"
    except Exception as e:
        jingrow.log_error("支付宝错误", f"处理失败: {str(e)}")
        return "fail"

@jingrow.whitelist(allow_guest=True)
def handle_wechatpay_notification():
    """处理微信支付通知回调"""
    try:
        # 获取请求数据
        headers = jingrow.local.request.headers
        body = jingrow.request.get_data()
        
        # 初始化微信支付API
        wechat_pay = WeChatPayAPI()
        
        # 使用SDK的方法解密回调数据
        try:            
            # 调用SDK提供的decrypt_callback方法解密数据
            decrypted_data = wechat_pay.wxpay.decrypt_callback(headers, body)
            
            # 如果返回值是字符串则解析为JSON
            if isinstance(decrypted_data, str):
                decrypted_data = json.loads(decrypted_data)
                            
            # 获取关键字段
            order_id = decrypted_data.get("out_trade_no")
            trade_no = decrypted_data.get("transaction_id")
            trade_state = decrypted_data.get("trade_state")
            total_amount = decrypted_data.get("amount", {}).get("total", 0) / 100  # 转换为元
            team_name = decrypted_data.get("attach", "")
                        
            # 确认交易状态为成功
            if trade_state != "SUCCESS":
                jingrow.log_error(f"微信支付交易状态不成功: {trade_state}", "微信支付通知")
                return "SUCCESS"  # 返回成功以避免微信重复通知
            
            # 查询支付记录
            payment_record = jingrow.db.get_value(
                "Order", 
                {"order_id": order_id}, 
                ["name", "total_amount", "status", "team"],
                as_dict=True
            )
                        
            if not payment_record:
                jingrow.log_error(f"未找到支付记录: {order_id}", "微信支付错误")
                return "SUCCESS"
            
            # 检查记录状态，避免重复处理
            if payment_record.status == "交易成功":
                jingrow.log_error(f"订单已处理: {order_id}", "微信支付通知")
                return "SUCCESS"
                        
            # 更新订单记录状态
            jingrow.db.set_value(
                "Order", 
                payment_record.name,
                {
                    "status": "已支付",
                    "trade_no": trade_no,
                    "payment_method": "微信支付"
                }
            )
            
            # 执行支付完成后的业务逻辑
            handle_order_payment_complete(order_id)
            
            # 立即提交数据库事务
            jingrow.db.commit()            
            
            return "SUCCESS"
            
        except Exception as e:
            jingrow.log_error("微信支付解密错误", f"处理微信支付通知数据失败: {str(e)}\n请求头: {headers}\n请求体: {body}")
            return "SUCCESS"  # 返回成功避免微信重复发送通知
            
    except Exception as e:
        jingrow.log_error("微信支付错误", f"处理微信支付通知失败: {str(e)}")
        return "SUCCESS"  # 返回成功避免微信重复发送通知


@jingrow.whitelist(allow_guest=True)
def handle_paypal_return():
    """处理PayPal支付成功后的返回"""
    try:
        # 获取PayPal返回的参数
        params = jingrow.request.args
        payment_id = params.get("paymentId")
        token = params.get("token")
        payer_id = params.get("PayerID")
        
        if not token:
            jingrow.log_error("PayPal返回参数错误", "未获取到token")
            # 跳转到充值失败页面
            return jingrow.redirect(jingrow.utils.get_url("/dashboard/billing?payment_status=failed"))
        
        # 根据token查找订单记录
        payment_record = jingrow.db.get_value(
            "Order", 
            {"order_id": token, "payment_method": "PayPal"},
            ["name", "total_amount", "status", "team"],
            as_dict=True
        )
        
        if not payment_record:
            jingrow.log_error(f"未找到PayPal支付记录: {token}", "PayPal返回处理")
            return jingrow.redirect(jingrow.utils.get_url("/dashboard/billing?payment_status=failed"))
        
        # 检查记录状态
        if payment_record.status == "交易成功":
            # 订单已处理，跳转到成功页面
            return jingrow.redirect(jingrow.utils.get_url("/dashboard/billing?payment_status=success"))
        
        # 更新订单记录状态为已支付
        jingrow.db.set_value(
            "Order", 
            payment_record.name,
            {
                "status": "已支付",
                "trade_no": payment_id,
                "payer_id": payer_id
            }
        )
        
        # 执行支付完成后的业务逻辑
        handle_order_payment_complete(token)
        
        # 提交事务
        jingrow.db.commit()
        
        # 跳转到充值成功页面
        return jingrow.redirect(jingrow.utils.get_url("/dashboard/billing?payment_status=success"))
        
    except Exception as e:
        jingrow.log_error("PayPal返回处理错误", f"处理PayPal支付返回失败: {str(e)}")
        return jingrow.redirect(jingrow.utils.get_url("/dashboard/billing?payment_status=failed"))


@jingrow.whitelist(allow_guest=True)
def handle_paypal_cancel():
    """处理PayPal支付取消的返回"""
    try:
        # 获取PayPal返回的参数
        params = jingrow.request.args
        token = params.get("token")
        
        if token:
            # 根据token查找订单记录
            payment_record = jingrow.db.get_value(
                "Order", 
                {"order_id": token, "payment_method": "PayPal"},
                "name"
            )
            
            if payment_record:
                # 更新订单记录状态为已取消
                jingrow.db.set_value("Order", payment_record, "status", "已取消")
                jingrow.db.commit()
        
        # 跳转到充值页面
        return jingrow.redirect(jingrow.utils.get_url("/dashboard/billing?payment_status=canceled"))
        
    except Exception as e:
        jingrow.log_error("PayPal取消处理错误", f"处理PayPal支付取消失败: {str(e)}")
        return jingrow.redirect(jingrow.utils.get_url("/dashboard/billing"))


@jingrow.whitelist(allow_guest=True)
def handle_paypal_webhook():
    """处理PayPal支付结果通知回调"""
    try:
        # 获取请求数据
        headers = jingrow.request.headers
        body = jingrow.request.get_data()
        
        # 初始化PayPal API
        paypal_api = PayPalAPI()
        
        # 验证webhook通知
        if not paypal_api.verify_webhook(headers, body):
            jingrow.log_error("PayPal webhook验证失败", "PayPal Webhook")
            return "FAIL"
        
        # 解析通知数据
        webhook_data = json.loads(body)
        event_type = webhook_data.get("event_type")
        resource = webhook_data.get("resource")
        
        if not resource:
            jingrow.log_error("PayPal webhook数据错误", "PayPal Webhook")
            return "SUCCESS"
        
        # 处理支付完成事件
        if event_type == "CHECKOUT.ORDER.APPROVED":
            order_id = resource.get("id")
            
            # 根据订单ID查找本地订单记录
            payment_record = jingrow.db.get_value(
                "Order", 
                {"order_id": order_id, "payment_method": "PayPal"},
                ["name", "total_amount", "status", "team"],
                as_dict=True
            )
            
            if not payment_record:
                jingrow.log_error(f"未找到PayPal订单记录: {order_id}", "PayPal Webhook")
                return "SUCCESS"
            
            # 检查记录状态，避免重复处理
            if payment_record.status == "交易成功":
                return "SUCCESS"
            
            # 捕获支付金额
            try:
                capture_result = paypal_api.capture_payment(order_id)
                
                # 检查捕获状态
                if capture_result.get("status") == "COMPLETED":
                    # 更新订单记录状态
                    jingrow.db.set_value(
                        "Order", 
                        payment_record.name,
                        {
                            "status": "已支付",
                            "trade_no": capture_result.get("id"),
                            "payer_id": resource.get("payer", {}).get("payer_id")
                        }
                    )
                    
                    # 执行支付完成后的业务逻辑
                    handle_order_payment_complete(order_id)
                    
                    # 提交事务
                    jingrow.db.commit()
                    
            except Exception as e:
                jingrow.log_error(f"捕获PayPal支付失败: {str(e)}", "PayPal Webhook")
        
        return "SUCCESS"
        
    except Exception as e:
        error_message = (
            "处理PayPal webhook失败:\n"
            f"异常信息: {str(e)}\n"
            f"堆栈信息:\n{traceback.format_exc()}\n"
        )
        jingrow.log_error(error_message, "PayPal Webhook Error")
        return "FAIL"


def handle_order_payment_complete(order_id):
    """处理订单支付完成后的业务逻辑"""
    try:
        order = jingrow.get_pg("Order", {"order_id": order_id})
        
        # 根据订单类型执行不同的业务逻辑
        if order.order_type == "余额充值":
            process_balance_recharge(order)
        elif order.order_type == "网站续费":
            process_site_renew(order_id)
        elif order.order_type == "服务器续费":
            # 异步续费服务器
            jingrow.enqueue('jcloud.api.aliyun_server_light.renew_server', order_name=order.name)
        elif order.order_type == "服务器升级":
            # 异步升级服务器
            jingrow.enqueue('jcloud.api.aliyun_server_light.upgrade_server', order_name=order.name)
        elif order.order_type == "新建服务器":
            # 异步创建服务器
            jingrow.enqueue('jcloud.api.aliyun_server_light.create_aliyun_server', order_name=order.name)
        elif order.order_type == "域名注册":
            # 异步注册域名
            jingrow.enqueue('jcloud.api.domain_west.register_domain_from_order', order_name=order.name)
        elif order.order_type == "域名续费":
            # 异步续费域名
            jingrow.enqueue('jcloud.api.domain_west.renew_domain_from_order', order_name=order.name)
        
        return True
    except Exception as e:
        jingrow.log_error("订单处理错误", f"处理订单 {order_id} 支付完成事件失败: {str(e)}")
        return False

def process_balance_recharge(order):
    """处理余额充值业务逻辑"""
    try:        
        balance_transaction = jingrow.get_pg({
            "pagetype": "Balance Transaction",
            "team": order.team,
            "type": "Adjustment",
            "source": "Prepaid Credits",
            "amount": order.total_amount,
            "description": f"{order.payment_method}充值 (订单: {order.order_id})",
        })
        
        balance_transaction.flags.ignore_permissions = True
        balance_transaction.insert()
        balance_transaction.submit()
		
        # 更新订单状态为交易成功
        jingrow.db.set_value("Order", order.name, "status", "交易成功")
        jingrow.db.commit()

    except Exception as e:
        jingrow.log_error("余额充值错误", f"余额充值失败: 团队 {order.team}, 金额 {order.total_amount}, 错误: {str(e)}")
        raise

def process_site_renew(order_id):
    """处理网站续费，更新到期时间"""
    # 获取订单文档
    order = jingrow.get_pg("Order", {"order_id": order_id})
    
    # 检查订单状态，避免重复处理
    if order.status == "交易成功":
        jingrow.log_error(
            message=f"订单 {order_id} 已处理完成，跳过重复处理",
            title="站点续费提示"
        )
        return {
            "name": order.title,
            "url": order.title,
            "new_end_date": jingrow.db.get_value("Site", order.title, "site_end_date"),
            "already_processed": True
        }
    
    # 从订单中提取信息
    site_name = order.title  # 网站URL保存在订单的title字段中
    renewal_months = int(order.description)  # 续费月数保存在订单的description字段中
    
    # 获取站点文档
    site = jingrow.get_pg("Site", site_name)
    
    # 计算新的到期日期
    current_end_date = getdate(site.site_end_date or jingrow.utils.today())
    if current_end_date < getdate(jingrow.utils.today()):
        current_end_date = getdate(jingrow.utils.today())
        
    new_end_date = add_months(current_end_date, renewal_months)
    
    # 更新站点到期日期
    site.site_end_date = new_end_date
    site.save(ignore_permissions=True)

    # 续费后自动激活站点（如有需要）
    if site.status in ["Inactive", "Suspended"]:
        try:
            site.activate()
        except Exception as e:
            jingrow.log_error("站点自动激活失败", f"站点 {site_name} 续费后自动激活失败: {str(e)}")
    
    # 更新订单状态为交易成功，防止重复处理
    jingrow.db.set_value("Order", order.name, "status", "交易成功")
    
    return {
        "name": site.name,
        "url": site_name,
        "new_end_date": new_end_date
    }

@jingrow.whitelist()
def check_payment_status(order_id, payment_type):
    """检查支付状态"""
    if payment_type in ["alipay", "wechatpay", "paypal"]:
        pagetype = "Order"
    else:
        jingrow.throw("不支持的支付类型")
    
    team = get_current_team()
    payment_record = jingrow.db.get_value(
        pagetype, 
        {"order_id": order_id, "team": team},
        ["status", "total_amount"],
        as_dict=True
    )
    
    if not payment_record:
        return {"status": "not_found"}
    
    return payment_record


@jingrow.whitelist()
def create_alipay_order_for_recharge(amount):
    """创建支付宝订单用于购买预付费信用额度"""
    team = get_current_team(True)
    
    # 金额取整到两位小数
    total_amount = round(float(amount), 2)
    
    # 生成唯一订单号
    order_id = datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3] + ''.join(random.choices('0123456789', k=6))
    
    # 创建订单记录
    payment_record = jingrow.get_pg({
        "pagetype": "Order",
        "order_id": order_id,
        "order_type": "余额充值",
        "team": team.name,
        "total_amount": float(total_amount),
        "status": "待支付",
        "payment_method": "支付宝"
    })
    
    payment_record.insert(ignore_permissions=True)
    jingrow.db.commit()
	    
    # 直接使用AlipayAPI类生成支付链接
    api = AlipayAPI()
    
    try:
        # 生成支付链接，使用API类中已配置的默认URL
        payment_url = api.generate_payment_url(
            order_id=order_id,
            amount=amount,
            subject="Jingrow 余额充值",
            team_name=team.name
        )
        
        return {
            "payment_url": payment_url,
            "order_id": order_id,
            "payment_record": payment_record.name
        }
    except Exception as e:
        jingrow.log_error("Order", f"创建支付宝订单失败: {str(e)}")
        jingrow.throw(f"创建支付宝订单失败: {str(e)}")


def generate_qr_code(payment_url):
    """生成二维码图片的Base64字符串"""
    qr = segno.make(payment_url)
    buffer = io.BytesIO()
    qr.save(buffer, kind='png', scale=6)
    img_str = base64.b64encode(buffer.getvalue()).decode("utf-8")
    return f"data:image/png;base64,{img_str}"


@jingrow.whitelist()
def create_wechatpay_order_for_recharge(amount):
    """创建微信支付订单用于购买预付费信用额度"""
    team = get_current_team(True)
    total_amount = round(float(amount), 2)
    
    # 生成唯一订单号
    order_id = datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3] + ''.join(random.choices('0123456789', k=6))
    
    # 创建订单记录
    payment_record = jingrow.get_pg({
        "pagetype": "Order",
        "order_id": order_id,
        "order_type": "余额充值",
        "team": team.name,
        "total_amount": float(total_amount),
        "status": "待支付",
        "payment_method": "微信支付"
    })
    
    payment_record.insert(ignore_permissions=True)
    jingrow.db.commit()
    
    # 使用WeChatPayAPI生成支付链接
    wechat_pay = WeChatPayAPI()
    
    try:
        qr_code_url = wechat_pay.generate_payment_url(
            order_id=order_id,
            amount=amount,
            subject="Jingrow 余额充值",
            team_name=team.name
        )
        
        # 检查URL是否为空
        if not qr_code_url:
            jingrow.log_error("微信支付错误", "微信支付URL生成为空")      
        
        # 使用提供的函数生成二维码图片
        qr_code_image = generate_qr_code(qr_code_url)       
        result = {
            "qr_code_url": qr_code_url,
            "qr_code_image": qr_code_image,
            "order_id": order_id,
            "payment_record": payment_record.name
        }        
        return result
        
    except Exception as e:
        jingrow.log_error("微信支付错误", f"创建微信支付订单失败: {str(e)}")
        jingrow.throw(f"创建微信支付订单失败")


@jingrow.whitelist()
def create_paypal_order_for_recharge(amount):
    """创建PayPal订单用于购买预付费信用额度"""
    team = get_current_team(True)
    total_amount = round(float(amount), 2)
    
    # 生成唯一订单号
    order_id = datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3] + ''.join(random.choices('0123456789', k=6))
    
    # 创建订单记录
    payment_record = jingrow.get_pg({
        "pagetype": "Order",
        "order_id": order_id,
        "order_type": "余额充值",
        "team": team.name,
        "total_amount": float(total_amount),
        "status": "待支付",
        "payment_method": "PayPal"
    })
    
    payment_record.insert(ignore_permissions=True)
    jingrow.db.commit()
    
    try:
        # 使用PayPalAPI类生成支付链接
        api = PayPalAPI()
        
        # 生成支付链接，使用默认的返回和取消URL
        payment_url = api.generate_payment_url(
            order_id=order_id,
            amount=total_amount,
            subject="Jingrow 余额充值",
            team_name=team.name
        )
        
        return {
            "payment_url": payment_url,
            "order_id": order_id,
            "payment_record": payment_record.name
        }
        
    except Exception as e:
        jingrow.log_error("PayPal支付错误", f"创建PayPal订单失败: {str(e)}")
        jingrow.throw(f"创建PayPal订单失败")


@jingrow.whitelist()
def create_order(**kwargs):
    """创建站点订单"""
    try:
        # 从kwargs中获取参数，更灵活，且使用正确的字段名
        title = kwargs.get('title')
        description = kwargs.get('description')
        total_amount = kwargs.get('total_amount')
        order_type = kwargs.get('order_type')
        
        # 参数验证
        if not title or not description or not total_amount:
            jingrow.throw("必须提供标题、描述和金额")
            
        # 获取当前用户团队
        team = get_current_team(True)
        
        # 生成唯一订单号
        order_id = datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3] + ''.join(random.choices('0123456789', k=6))
        
        # 创建订单记录
        order = jingrow.get_pg({
            "pagetype": "Order",
            "order_id": order_id,
			"order_type": order_type,
            "title": title,
            "description": description,
            "team": team.name,
            "total_amount": float(total_amount),
            "status": "待支付",
        })
        
        order.insert(ignore_permissions=True)
        jingrow.db.commit()
        
        return {
            "success": True,
            "order": order.as_dict()
        }
        
    except Exception as e:
        jingrow.log_error("订单错误", f"创建站点订单失败: {str(e)}")
        return {
            "success": False,
            "message": f"创建订单失败: {str(e)}"
        }


@jingrow.whitelist()
def create_renewal_order(site, renewal_months=1):
    """创建网站续费订单"""
    try:
        # 验证输入
        site_pg = jingrow.get_pg("Site", site)
        site_url = f"{site_pg.subdomain}.{site_pg.domain}"
        team = site_pg.team
        
        # 验证当前用户权限
        current_team = get_current_team(True)
        if current_team.name != team:
            jingrow.throw("您没有权限为此站点创建续费订单")
        
        # 获取当前计划 - 使用正确的字段名 plan 而非 current_plan
        current_plan = jingrow.get_pg("Site Plan", site_pg.plan)
        
        # 计算续费金额
        renewal_months = int(renewal_months)
        team_currency = jingrow.db.get_value("Team", team, "currency")
        
        if renewal_months == 12:
            # 年付9折
            amount = round(current_plan.price_cny * 12 * 0.9) if team_currency == "CNY" else round(current_plan.price_usd * 12 * 0.9)
        else:
            amount = current_plan.price_cny * renewal_months if team_currency == "CNY" else current_plan.price_usd * renewal_months
        
        # 生成唯一订单号
        order_id = datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3] + ''.join(random.choices('0123456789', k=6))
        
        # 创建订单记录
        order = jingrow.get_pg({
            "pagetype": "Order",
            "order_id": order_id,
            "order_type": "网站续费",
            "team": team,
            "status": "待支付",
            "total_amount": amount,
            "title": site_url,
            "description": str(renewal_months)  # 简单存储续费月数
        })
        
        order.insert(ignore_permissions=True)
        jingrow.db.commit()
        
        return {
            "success": True,
            "order": order.as_dict()
        }
    except Exception as e:
        jingrow.log_error("续费订单错误", f"创建续费订单失败: {str(e)}")
        return {
            "success": False,
            "message": f"创建续费订单失败: {str(e)}"
        }

@jingrow.whitelist()
def process_balance_payment_for_order(order_id):
    """使用账户余额支付订单"""
    try:
        # 获取当前用户团队
        team = get_current_team(True)
        
        # 获取订单信息
        order = jingrow.get_pg("Order", {"order_id": order_id})
        if not order:
            jingrow.throw(f"找不到订单: {order_id}")
            
        # 验证订单是否属于当前团队
        if order.team != team.name:
            jingrow.throw("您没有权限支付此订单")
            
        # 检查订单状态
        if order.status != "待支付":
            return {
                "success": False,
                "message": "该订单已支付或已取消"
            }
            
        # 使用 Team 类的 get_balance 方法获取余额
        balance = team.get_balance()
        
        # 检查余额是否足够
        if balance < order.total_amount:
            return {
                "success": False,
                "message": "余额不足"
            }
            
        # 创建余额交易记录（扣款）
        balance_transaction = jingrow.get_pg({
            "pagetype": "Balance Transaction",
            "team": team.name,
            "type": "Adjustment",
            "source": "Prepaid Credits",
            "amount": -1 * float(order.total_amount),  # 使用负数表示扣减
            "description": f"{order.order_type}-{order.title}",
            "paid_via_local_pg": 1
        })
        balance_transaction.flags.ignore_permissions = True
        balance_transaction.insert()
        balance_transaction.submit()
        
        # 更新订单状态
        order.status = "已支付"
        order.payment_method = "余额支付"
        order.save(ignore_permissions=True)
        jingrow.db.commit()
        
        return {
            "status": "Success",
            "message": "支付成功",
            "order": order.as_dict()
        }
        
    except Exception as e:
        jingrow.log_error("支付错误", f"余额支付失败: {str(e)}")
        return {
            "status": "Error",
            "message": f"余额支付失败: {str(e)}"
        }

@jingrow.whitelist()
def process_balance_payment_for_renew_order(order_id):
    """使用账户余额支付网站续费订单"""
    try:
        # 获取当前用户团队
        team = get_current_team(True)
        
        # 获取订单信息
        order = jingrow.get_pg("Order", {"order_id": order_id})
        if not order:
            jingrow.throw(_(f"找不到订单: {order_id}"))
            
        # 验证订单是否属于当前团队
        if order.team != team.name:
            jingrow.throw(_("您没有权限支付此订单"))
            
        # 验证订单类型
        if order.order_type != "网站续费":
            jingrow.throw(_("此订单不是网站续费订单"))
            
        # 检查订单状态
        if order.status != "待支付":
            return {
                "success": False,
                "message": _("该订单已支付或已取消")
            }
            
        # 使用 Team 类的 get_balance 方法获取余额
        balance = team.get_balance()
        
        # 检查余额是否足够
        if balance < order.total_amount:
            return {
                "success": False,
                "message": _("余额不足")
            }
            
        # 开始数据库事务
        jingrow.db.begin()
        
        try:
            # 创建余额交易记录（扣款）
            balance_transaction = jingrow.get_pg({
                "pagetype": "Balance Transaction",
                "team": team.name,
                "type": "Adjustment",
                "source": "Prepaid Credits",
                "amount": -1 * float(order.total_amount),  # 使用负数表示扣减
                "description": f"网站续费: {order.title}",
                "paid_via_local_pg": 1
            })
            balance_transaction.flags.ignore_permissions = True
            balance_transaction.insert()
            balance_transaction.submit()
            
            # 更新订单状态
            order.status = "已支付"
            order.payment_method = "余额支付"
            order.save(ignore_permissions=True)
            
            # 提取网站URL和续费周期
            site_name = order.title  # 网站URL就是name字段
            renewal_months = int(order.description)
            
            # 调用网站续期处理函数
            renew_result = process_site_renew(order_id)
            
            # 提交数据库事务
            jingrow.db.commit()
            
            return {
                "success": True,
                "status": "Success",
                "message": _("支付成功，网站已续费"),
                "order": order.as_dict(),
                "site": renew_result
            }
            
        except Exception as inner_error:
            # 回滚事务
            jingrow.db.rollback()
            raise inner_error
            
    except Exception as e:
        jingrow.log_error("续费支付错误", f"余额支付续费失败: {str(e)}")
        return {
            "success": False,
            "status": "Error",
            "message": _(f"余额支付失败: {str(e)}")
        }

@jingrow.whitelist()
def process_balance_payment_for_server_order(order_id):
    """使用账户余额支付订单"""
    try:
        # 获取当前用户团队
        team = get_current_team(True)
        
        # 获取订单信息
        order = jingrow.get_pg("Order", {"order_id": order_id})
        if not order:
            jingrow.throw(f"找不到订单: {order_id}")
            
        # 验证订单是否属于当前团队
        if order.team != team.name:
            jingrow.throw("您没有权限支付此订单")
            
        # 检查订单状态
        if order.status != "待支付":
            return {
                "success": False,
                "message": "该订单已支付或已取消"
            }
            
        # 使用 Team 类的 get_balance 方法获取余额
        balance = team.get_balance()
        
        # 检查余额是否足够
        if balance < order.total_amount:
            return {
                "success": False,
                "message": "余额不足"
            }
            
        # 创建余额交易记录（扣款）
        balance_transaction = jingrow.get_pg({
            "pagetype": "Balance Transaction",
            "team": team.name,
            "type": "Adjustment",
            "source": "Prepaid Credits",
            "amount": -1 * float(order.total_amount),  # 使用负数表示扣减
            "description": f"{order.order_type}-{order.title}",
            "paid_via_local_pg": 1
        })
        balance_transaction.flags.ignore_permissions = True
        balance_transaction.insert()
        balance_transaction.submit()
        
        # 更新订单状态
        order.status = "已支付"
        order.payment_method = "余额支付"
        order.save(ignore_permissions=True)
        jingrow.db.commit()
        
        # 支付成功后，调用订单完成处理函数
        handle_order_payment_complete(order_id)
        
        return {
            "status": "Success",
            "message": "支付成功",
            "order": order.as_dict()
        }
        
    except Exception as e:
        jingrow.log_error("支付错误", f"余额支付失败: {str(e)}")
        return {
            "status": "Error",
            "message": f"余额支付失败: {str(e)}"
        }


@jingrow.whitelist()
def process_alipay_order(order_id):
    """创建支付宝订单支付链接"""
    team = get_current_team(True)
    
    # 获取订单信息
    order = jingrow.get_pg("Order", {"order_id": order_id})
    if not order:
        jingrow.throw(f"找不到订单: {order_id}")
        
    # 验证订单是否属于当前团队
    if order.team != team.name:
        jingrow.throw("您没有权限支付此订单")
        
    # 检查订单状态
    if order.status != "待支付":
        jingrow.throw("该订单已支付或已取消")
    
    # 金额取整到两位小数
    amount = round(float(order.total_amount), 2)
    
    # 直接使用AlipayAPI类生成支付链接
    api = AlipayAPI()
    
    try:
        # 生成支付链接
        payment_url = api.generate_payment_url(
            order_id=order_id,
            amount=amount,
            subject=order.title or "Jingrow 站点订单",
            team_name=team.name
        )
        
        # 更新订单支付方式
        order.payment_method = "支付宝"
        order.save(ignore_permissions=True)
        
        return {
            "payment_url": payment_url,
            "order_id": order_id,
            "success": True
        }
    except Exception as e:
        jingrow.log_error("Order", f"创建支付宝订单失败: {str(e)}")
        jingrow.throw(f"创建支付宝订单失败: {str(e)}")

@jingrow.whitelist()
def process_wechatpay_order(order_id):
    """创建微信支付订单"""
    try:
        # 获取当前用户团队
        team = get_current_team(True)
        
        # 获取订单信息
        order = jingrow.get_pg("Order", {"order_id": order_id})
        if not order:
            jingrow.throw(f"找不到订单: {order_id}")
            
        # 验证订单是否属于当前团队
        if order.team != team.name:
            jingrow.throw("您没有权限支付此订单")
            
        # 检查订单状态
        if order.status != "待支付":
            jingrow.throw("该订单已支付或已取消")
            
        # 获取金额
        amount = order.total_amount
            
        # 创建微信支付客户端
        wechat_pay = WeChatPayAPI()
        
        try:
            # 生成支付URL
            qr_code_url = wechat_pay.generate_payment_url(
                order_id=order_id,
                amount=amount,
                subject=order.title or "Jingrow 站点订单",
                team_name=team.name
            )
            
            # 检查URL是否为空
            if not qr_code_url:
                jingrow.log_error("微信支付错误", "微信支付URL生成为空")      
                jingrow.throw("生成支付URL失败")
            
            # 生成二维码图片
            qr_code_image = generate_qr_code(qr_code_url)
            
            # 更新订单支付方式
            order.payment_method = "微信支付"
            order.save(ignore_permissions=True)
            
            return {
                "payment_url": qr_code_url,
                "qr_code_image": qr_code_image,
                "order_id": order_id,
                "success": True
            }
            
        except Exception as e:
            jingrow.log_error("微信支付错误", f"创建微信支付订单失败: {str(e)}")
            jingrow.throw(f"创建微信支付订单失败")
    
    except Exception as e:
        jingrow.log_error("微信支付错误", f"创建微信支付订单失败: {str(e)}")
        jingrow.throw(f"创建微信支付订单失败")

@jingrow.whitelist()
def check_order_payment_status(order_id):
    """检查订单支付状态"""
    try:
        # 获取订单信息
        order = jingrow.get_pg("Order", {"order_id": order_id})
        if not order:
            jingrow.throw(f"找不到订单: {order_id}")
            
        return {
            "success": True,
            "status": order.status,
            "order": order.as_dict()
        }
        
    except Exception as e:
        jingrow.log_error("订单错误", f"检查订单状态失败: {str(e)}")
        return {
            "success": False,
            "message": f"检查订单状态失败: {str(e)}"
        }

@jingrow.whitelist()
def get_orders(page=1, page_size=20, search=None):

    try:
        # 获取当前用户团队
        team = get_current_team(True)
        
        # 构建过滤条件
        filters = {"team": team.name}
        
        # 添加搜索条件
        if search:
            filters = [
                ["Order", "team", "=", team.name],
                [
                    "Order", 
                    "name|order_id|title|description", 
                    "like", 
                    f"%{search}%"
                ]
            ]
        
        # 计算分页参数
        page = int(page)
        page_size = int(page_size)
        start = (page - 1) * page_size
        
        # 获取订单总数
        total_count = jingrow.db.count("Order", filters=filters)
        
        # 获取分页后的订单列表 - 根据需求修改字段列表
        orders = jingrow.get_all(
            "Order",
            filters=filters,
            fields=[
                "title", 
                "order_id",
                "trade_no", 
                "order_type",
                "payment_method", 
                "description",
                "total_amount as total",
                "status", 
                "creation"
            ],
            order_by="creation desc",
            start=start,
            limit=page_size
        )
        
        # 记录日志以便调试
        jingrow.logger().info(f"获取订单成功: 团队={team.name}, 总数={total_count}")
        
        return {
            "orders": orders,
            "total": total_count
        }
        
    except Exception as e:
        jingrow.log_error("订单列表错误", f"获取订单列表失败: {str(e)}")
        return {
            "orders": [],
            "total": 0,
            "error": str(e)
        }

@jingrow.whitelist()
def get_order_details(name):
    """
    获取订单详情
    
    参数:
    name (str): 订单名称
    
    返回:
    dict: 包含订单详情
    """
    try:
        # 获取当前用户团队
        team = get_current_team(True)
        
        # 获取订单详情
        order = jingrow.get_pg("Order", name)
        
        # 验证订单是否属于当前团队
        if order.team != team.name:
            jingrow.throw("您无权查看此订单")
        
        # 构建返回数据
        order_dict = order.as_dict()
        
        return {
            "order": order_dict
        }
        
    except Exception as e:
        jingrow.log_error("订单详情错误", f"获取订单详情失败: {str(e)}")
        return {
            "error": str(e)
        }

@jingrow.whitelist()
def get_balance_transactions(page=1, page_size=20, search=None):
    """
    获取余额变动记录列表
    
    参数:
    page (int): 页码，默认为1
    page_size (int): 每页记录数，默认为20
    search (str): 搜索关键词，可选
    
    返回:
    dict: 包含transactions列表和total总数
    """
    try:
        # 获取当前用户团队
        team = get_current_team(True)
        
        # 构建基础过滤条件
        filters = {"team": team.name, "pagestatus": 1}  # 已提交的文档
        
        # 添加搜索条件（如果提供）
        if search:
            filters = [
                ["Balance Transaction", "team", "=", team.name], 
                ["Balance Transaction", "pagestatus", "=", 1],
                [
                    "Balance Transaction", 
                    "description|source|type|invoice", 
                    "like", 
                    f"%{search}%"
                ]
            ]
        
        # 计算分页参数
        page = int(page)
        page_size = int(page_size)
        start = (page - 1) * page_size
        
        # 获取总记录数
        total_count = jingrow.db.count("Balance Transaction", filters=filters)
        
        # 获取分页数据
        transactions = jingrow.get_all(
            "Balance Transaction",
            filters=filters,
            fields=[
                "name", 
                "creation", 
                "description", 
                "amount", 
                "ending_balance", 
                "type", 
                "source", 
                "invoice"
            ],
            order_by="creation desc",
            start=start,
            limit=page_size
        )
        
        return {
            "transactions": transactions,
            "total": total_count
        }
        
    except Exception as e:
        jingrow.log_error("余额记录错误", f"获取余额记录失败: {str(e)}")
        return {
            "transactions": [],
            "total": 0,
            "error": str(e)
        }

@jingrow.whitelist()
def process_balance_payment_for_domain_order(order_id):
    """处理域名订单的余额支付"""
    try:
        # 获取当前用户团队
        team = get_current_team(True)
        
        # 获取订单信息
        order = jingrow.get_pg("Order", {"order_id": order_id})
        if not order:
            jingrow.throw(f"找不到订单: {order_id}")
            
        # 验证订单是否属于当前团队
        if order.team != team.name:
            jingrow.throw("您没有权限支付此订单")
            
        # 检查订单状态
        if order.status != "待支付":
            return {
                "success": False,
                "message": "该订单已支付或已取消"
            }
            
        # 使用 Team 类的 get_balance 方法获取余额
        balance = team.get_balance()
        
        # 检查余额是否足够
        if balance < order.total_amount:
            return {
                "success": False,
                "message": "余额不足"
            }
            
        # 创建余额交易记录（扣款）
        balance_transaction = jingrow.get_pg({
            "pagetype": "Balance Transaction",
            "team": team.name,
            "type": "Adjustment",
            "source": "Prepaid Credits",
            "amount": -1 * float(order.total_amount),  # 使用负数表示扣减
            "description": f"{order.order_type}-{order.title}",
            "paid_via_local_pg": 1
        })
        balance_transaction.flags.ignore_permissions = True
        balance_transaction.insert()
        balance_transaction.submit()
        
        # 更新订单状态
        order.status = "已支付"
        order.payment_method = "余额支付"
        order.save(ignore_permissions=True)
        jingrow.db.commit()
        
        # 支付成功，订单状态已更新
        
        # 调用统一的订单支付完成处理函数
        handle_order_payment_complete(order_id)
        
        return {
            "status": "Success",
            "message": "支付成功",
            "order": order.as_dict()
        }
        
    except Exception as e:
        jingrow.log_error("支付错误", f"域名订单余额支付失败: {str(e)}")
        return {
            "status": "Error",
            "message": f"余额支付失败: {str(e)}"
        }







