<?php

namespace StoreEngine\Addons\Paddle;

use StoreEngine\Classes\AbstractAjaxHandler;
use StoreEngine\Classes\Order;
use StoreEngine\Payment_Gateways;
use StoreEngine\Utils\Helper;

class Ajax extends AbstractAjaxHandler {

	public static function init() {
		$self = new self();
		$self->dispatch_actions();
	}

	public function __construct() {
		$this->actions = [
			'payment_method/paddle/get_transaction_id' => [
				'callback'             => [ $this, 'get_transaction_id' ],
				'allow_visitor_action' => true,
				'fields'               => [
					'order_id' => 'integer',
				],
			],
			'payment_method/paddle/save_checkout_id'   => [
				'callback'             => [ $this, 'save_checkout_id' ],
				'allow_visitor_action' => true,
				'fields'               => [
					'order_id'       => 'integer',
					'checkout_id'    => 'string',
					'transaction_id' => 'string',
				],
			],
		];
	}

	public function get_transaction_id( array $payload ) {
		if ( empty( $payload['order_id'] ) ) {
			$order = Helper::get_recent_draft_order();
			$with_cart = true;
		} else {
			$order     = Helper::get_order( $payload['order_id'] );
			$with_cart = false;
		}

		if ( is_wp_error( $order ) ) {
			wp_send_json_error( [ 'message' => __( 'Order not found!', 'storeengine' ) ] );
		}

		$transaction_id = $order->get_transaction_id();
		if ( ! empty( $transaction_id ) && 'paddle' === $order->get_payment_method() ) {
			if ( $with_cart ) {
				$this->update_transaction_with_cart( $transaction_id );
			} else {
				$this->update_transaction_with_order( $transaction_id, $order );
			}
		} else {
			if ( $with_cart ) {
				$this->create_transaction_with_cart();
			} else {
				$this->create_transaction_with_order( $order );
			}
		}
	}

	private function create_transaction_with_cart() {
		$items = $this->prepare_cart_transaction_items();
		if ( empty( $items ) ) {
			wp_send_json_error( [ 'message' => __( 'No items found in cart.', 'storeengine' ) ] );
		}

		$cart = Helper::cart();
		if ( ! $cart ) {
			wp_send_json_error( [ 'message' => __( 'No cart found.', 'storeengine' ) ] );
		}

		$order       = Helper::get_recent_draft_order();
		$discount_id = null;
		if ( ! empty( $cart->get_coupon_discount_totals() ) ) {
			$response = PaddleService::init()->create_discount( $order->get_id(), $cart->get_coupon_discount_totals() );
			if ( is_wp_error( $response ) ) {
				wp_send_json_error( $response );
			}
			$discount_id = $response->data->id;
			$order->update_meta_data( '_paddle_discount_id', $discount_id );
		}

		$response = PaddleService::init()->create_transaction( $order->get_id(), $items, $discount_id );
		if ( is_wp_error( $response ) ) {
			wp_send_json_error( $response );
		}

		$order->set_transaction_id( $response->data->id );
		$order->save();

		wp_send_json_success( [ 'transaction_id' => $response->data->id ] );
	}

	private function create_transaction_with_order( Order $order ) {
		$items = $this->prepare_order_transaction_items( $order );
		if ( empty( $items ) ) {
			wp_send_json_error( [ 'message' => __( 'No items found in order.', 'storeengine' ) ] );
		}

		$discount_id = null;
		$discounts   = [];
		foreach ( $order->get_coupons() as $coupon_item ) {
			$discounts[ $coupon_item->get_code() ] = $coupon_item->get_discount();
		}

		if ( ! empty( $discounts ) ) {
			$response = PaddleService::init()->create_discount( $order->get_id(), $discounts );
			if ( is_wp_error( $response ) ) {
				wp_send_json_error( $response );
			}
			$discount_id = $response->data->id;
			$order->update_meta_data( '_paddle_discount_id', $discount_id );
		}

		$response = PaddleService::init()->create_transaction( $order->get_id(), $items, $discount_id );
		if ( is_wp_error( $response ) ) {
			wp_send_json_error( $response );
		}

		$order->set_transaction_id( $response->data->id );
		$order->save();

		wp_send_json_success( [ 'transaction_id' => $response->data->id ] );
	}

	private function prepare_cart_transaction_items(): array {
		$cart  = Helper::cart();
		$order = Helper::get_recent_draft_order();
		if ( ! $order || ! $cart ) {
			wp_send_json_error( [ 'message' => __( 'No order or cart found.', 'storeengine' ) ] );
		}

		$items          = [];
		$paddle_gateway = Payment_Gateways::init()->get_gateway( 'paddle' );
		if ( ! $paddle_gateway ) {
			wp_send_json_error( [ 'message' => __( 'Paddle gateway not found.', 'storeengine' ) ] );
		}

		$default_tax_category = $paddle_gateway->get_option( 'default_tax_category' );
		foreach ( $cart->get_cart_items() as $item ) {
			$product_tax = get_post_meta( $item->product_id, '_storeengine_paddle_tax_category', true );
			$items[]     = [
				'price'    => [
					'name'        => $item->price_name,
					'description' => "Product ID: $item->product_id \n Price Id: $item->price_id ",
					'tax_mode'    => $paddle_gateway->get_option( 'tax_mode', 'internal' ),
					'unit_price'  => [
						'amount'        => (string) PaddleService::get_paddle_amount( $item->price + ( $item->setup_fee ? $item->setup_fee_price : 0 ) ),
						'currency_code' => $order->get_currency(),
					],
					'custom_data' => [
						'merchant_product_id'   => $item->product_id,
						'merchant_price_id'     => $item->price_id,
						'merchant_variation_id' => $item->variation_id,
					],
					'product'     => [
						'name'         => $item->name . ( $item->setup_fee ? ' (with ' . ( empty( $item->setup_fee_name ) ? 'Setup Fee)' : $item->setup_fee_name . ')' ) : '' ),
						'tax_category' => ! empty( $product_tax ) ? $product_tax : $default_tax_category,
					],
				],
				'quantity' => $item->quantity,
			];
		}

		return $items;
	}

	private function prepare_order_transaction_items( Order $order ): array {
		$items          = [];
		$paddle_gateway = Payment_Gateways::init()->get_gateway( 'paddle' );
		if ( ! $paddle_gateway ) {
			wp_send_json_error( [ 'message' => __( 'Paddle gateway not found.', 'storeengine' ) ] );
		}

		$default_tax_category = $paddle_gateway->get_option( 'default_tax_category' );

		foreach ( $order->get_items() as $item ) {
			/** @var Order\OrderItemProduct $item */
			$product_tax  = $item->get_meta( '_paddle_tax_category' );
			$product_tax  = empty( $product_tax ) ? get_post_meta( $item->get_product_id(), '_storeengine_paddle_tax_category', true ) : $product_tax;
			$product_name = $item->get_name();

			if ( $item->get_setup_fee() && ! $order->get_meta( '_subscription_renewal' ) ) {
				if ( $item->get_setup_fee_name() ) {
					// translators: %1$s. Product name, %2$s. Fee name.
					$product_name = sprintf( __( '%1$s (with %2$s)', 'storeengine' ), $product_name, $item->get_setup_fee_name() );
				} else {
					// translators: %s. Product name.
					$product_name = sprintf( __( '%s (with Setup Fee)', 'storeengine' ), $product_name );
				}
			}

			$items[] = [
				'price'    => [
					'name'        => $item->get_price_name(),
					'description' => sprintf(
					// translators: %1$s. Product ID, %2$s. Price ID.
						__( 'Product ID: %1$s, Price Id: %2$s', 'storeengine' ),
						$item->get_product_id(),
						$item->get_price_id()
					),
					'tax_mode'    => $paddle_gateway->get_option( 'tax_mode', 'internal' ),
					'unit_price'  => [
						'amount'        => (string) PaddleService::get_paddle_amount( $item->get_price() + ( $item->get_setup_fee() && ! $order->get_meta( '_subscription_renewal' ) ? $item->get_setup_fee_name() : 0 ) ),
						'currency_code' => $order->get_currency(),
					],
					'custom_data' => [
						'merchant_product_id'   => $item->get_product_id(),
						'merchant_price_id'     => $item->get_price_id(),
						'merchant_variation_id' => $item->get_variation_id(),
					],
					'product'     => [
						'name'         => $product_name,
						'tax_category' => ! empty( $product_tax ) ? $product_tax : $default_tax_category,
					],
				],
				'quantity' => $item->get_quantity(),
			];
		}

		return $items;
	}

	private function update_transaction_with_cart( string $transaction_id ) {
		$items = $this->prepare_cart_transaction_items();
		if ( empty( $items ) ) {
			wp_send_json_error( [ 'message' => __( 'No items found in cart.', 'storeengine' ) ] );
		}

		$order = Helper::get_recent_draft_order();
		if ( ! $order ) {
			wp_send_json_error( [ 'message' => __( 'No draft order found.', 'storeengine' ) ] );
		}
		$cart = Helper::cart();
		if ( ! $cart ) {
			wp_send_json_error( [ 'message' => __( 'No cart found.', 'storeengine' ) ] );
		}

		$discount_id   = ! empty( $order->get_meta( '_paddle_discount_id' ) ) ? $order->get_meta( '_paddle_discount_id' ) : null;
		$discount_hash = $order->get_meta( '_paddle_discount_coupons_hash' );
		if ( ! empty( $cart->get_coupon_discount_totals() ) && ( md5( wp_json_encode( $cart->get_coupon_discount_totals() ) ) !== $discount_hash || ! $discount_id ) ) {
			$response = PaddleService::init()->create_discount( $order->get_id(), $cart->get_coupon_discount_totals() );
			if ( is_wp_error( $response ) ) {
				wp_send_json_error( $response );
			}
			$discount_id = $response->data->id;
			$order->update_meta_data( '_paddle_discount_id', $discount_id );
			$order->update_meta_data( '_paddle_discount_coupons_hash', md5( wp_json_encode( $cart->get_coupon_discount_totals() ) ) );
			$order->save();
		} elseif ( $discount_id ) {
			$discount_id = null;
		}

		$response = PaddleService::init()->update_transaction( $transaction_id, [
			'discount_id' => $discount_id,
			'items'       => $items,
			'custom_data' => [
				'merchant_order_id' => $order->get_id(),
			],
		] );

		if ( is_wp_error( $response ) ) {
			wp_send_json_error( $response );
		}

		wp_send_json_success( [ 'transaction_id' => $response->data->id ] );
	}

	private function update_transaction_with_order( string $transaction_id, Order $order ) {
		$items = $this->prepare_order_transaction_items( $order );
		if ( empty( $items ) ) {
			wp_send_json_error( [ 'message' => __( 'No items found in order.', 'storeengine' ) ] );
		}

		$discount_id   = ! empty( $order->get_meta( '_paddle_discount_id' ) ) ? $order->get_meta( '_paddle_discount_id' ) : null;
		$discount_hash = $order->get_meta( '_paddle_discount_coupons_hash' );
		$discounts     = [];
		foreach ( $order->get_coupons() as $coupon_item ) {
			$discounts[ $coupon_item->get_code() ] = $coupon_item->get_discount();
		}

		if ( ! empty( $discounts ) && ( md5( wp_json_encode( $discounts ) ) !== $discount_hash || ! $discount_id ) ) {
			$response = PaddleService::init()->create_discount( $order->get_id(), $discounts );
			if ( is_wp_error( $response ) ) {
				wp_send_json_error( $response );
			}
			$discount_id = $response->data->id;
			$order->update_meta_data( '_paddle_discount_id', $discount_id );
			$order->update_meta_data( '_paddle_discount_coupons_hash', md5( wp_json_encode( $discounts ) ) );
			$order->save();
		} elseif ( $discount_id ) {
			$discount_id = null;
		}

		$response = PaddleService::init()->update_transaction( $transaction_id, [
			'discount_id' => $discount_id,
			'items'       => $items,
			'custom_data' => [
				'merchant_order_id' => $order->get_id(),
			],
		] );
		if ( is_wp_error( $response ) ) {
			wp_send_json_error( $response );
		}

		wp_send_json_success( [ 'transaction_id' => $response->data->id ] );
	}

	public function save_checkout_id( array $payload ) {
		if ( ! isset( $payload['checkout_id'] ) || ! isset( $payload['transaction_id'] ) ) {
			wp_send_json_error( [ 'message' => __( 'Checkout ID and Transaction ID are required.', 'storeengine' ) ] );
		}

		$order_id = $payload['order_id'] ?? null;

		if ( ! $order_id ) {
			$order = Helper::get_recent_draft_order();
		} else {
			$order = Helper::get_order( $order_id );
		}

		if ( ! $order ) {
			wp_send_json_error( [ 'message' => __( 'No order found.', 'storeengine' ) ] );
		}

		$order->set_transaction_id( $payload['transaction_id'] );
		$order->add_meta_data( '_paddle_checkout_id', $payload['checkout_id'] );
		$order->save();

		wp_send_json_success( [ 'success' => true ] );
	}
}
