<?php

namespace StoreEngine\Ajax;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use StoreEngine;
use StoreEngine\Classes\AbstractAjaxHandler;
use StoreEngine\Classes\AbstractRequestHandler;
use StoreEngine\Classes\Countries;
use StoreEngine\Classes\Exceptions\StoreEngineException;
use StoreEngine\Classes\Exceptions\StoreEngineNotFoundException;
use StoreEngine\Utils\Helper;
use StoreEngine\Utils\TaxUtil;
use StoreEngine\Utils\Template;

class Cart extends AbstractAjaxHandler {

	public function __construct() {
		$fields = apply_filters( 'storeengine/ajax/add-to-cart/fields', [
			'price_id'     => StoreEngine\Classes\AbstractRequestHandler::ID,
			'product_id'   => StoreEngine\Classes\AbstractRequestHandler::ID,
			'variation_id' => StoreEngine\Classes\AbstractRequestHandler::ID,
			'quantity'     => StoreEngine\Classes\AbstractRequestHandler::ABSINT,
		] );

		$this->actions = [
			'add_to_cart'               => [
				'callback'             => [ $this, 'add_to_cart' ],
				'allow_visitor_action' => true,
				'fields'               => $fields,
			],
			'direct_checkout'           => [
				'callback'             => [ $this, 'direct_checkout' ],
				'allow_visitor_action' => true,
				'fields'               => $fields,
			],
			'remove_cart_item'          => [
				'callback'             => [ $this, 'remove_cart_item' ],
				'allow_visitor_action' => true,
				'fields'               => [ 'item_key' => 'string' ],
			],
			'update_cart_item_quantity' => [
				'callback'             => [ $this, 'update_cart_item_quantity' ],
				'allow_visitor_action' => true,
				'fields'               => [
					'item_key' => 'string',
					'quantity' => AbstractRequestHandler::ABSINT,
				],
			],
			'clear_cart'                => [
				'callback'             => [ $this, 'clear_cart' ],
				'allow_visitor_action' => true,
			],
			'refresh_cart'              => [
				'callback'             => [ $this, 'refresh_cart' ],
				'allow_visitor_action' => true,
			],
		];
	}

	/**
	 * @throws StoreEngineException
	 */
	protected function validate_add_to_cart( array $payload = [] ): array {
		if ( empty( $payload['price_id'] ) ) {
			wp_send_json_error( esc_html__( 'Price ID is required.', 'storeengine' ) );
		}

		$price = new StoreEngine\Classes\Price( $payload['price_id'] );

		$product = $price->get_product();

		if ( ! $product ) {
			wp_send_json_error( esc_html__( 'Product not found.', 'storeengine' ) );
		}

		$quantity = $payload['quantity'] ?? 1;

		if ( ! $quantity ) {
			wp_send_json_error( esc_html__( 'Product quantity must be greater than zero.', 'storeengine' ) );
		}

		$data = [
			'price_id'       => $price->get_id(),
			'product_id'     => $product->get_id(),
			'quantity'       => $quantity,
			'variation_id'   => 0,
			'variation_data' => [],
		];

		if ( $product->is_type( 'variable' ) ) {
			if ( empty( $payload['variation_id'] ) ) {
				wp_send_json_error( esc_html__( 'Variation id is required.', 'storeengine' ) );
			}

			$variation = Helper::get_product_variation( $payload['variation_id'] );

			if ( ! $variation ) {
				wp_send_json_error( esc_html__( 'Invalid variation ID.', 'storeengine' ) );
			}

			$data['variation_id'] = $variation->get_id();

			foreach ( $variation->get_attributes() as $attributeData ) {
				$data['variation_data'][ $attributeData->taxonomy ] = $attributeData->slug;
			}
		}

		return $data;
	}

	protected function add_to_cart_response( $product_id, $price_id, $redirect = false ) {
		$data = [ 'item' => Helper::cart()->get_cart_item_by_product( $product_id, $price_id ) ];

		if ( $redirect ) {
			$data['redirect'] = esc_url( Helper::get_checkout_url() );
		}

		return apply_filters( 'storeengine/ajax/cart/add_to_cart_response', $data, $product_id, $price_id );
	}

	protected function add_to_cart( $payload ) {
		try {
			[
				'price_id'       => $price_id,
				'product_id'     => $product_id,
				'quantity'       => $quantity,
				'variation_id'   => $variation_id,
				'variation_data' => $variation_data,
			] = $this->validate_add_to_cart( $payload );

			$result = Helper::cart()->add_product_to_cart( $price_id, $quantity, $variation_id, $variation_data );

			if ( is_wp_error( $result ) ) {
				wp_send_json_error( $result->get_error_message() );
			}

			do_action( 'storeengine/ajax/cart/added_to_cart', $payload );

			wp_send_json_success( $this->add_to_cart_response( $product_id, $price_id ) );
		} catch ( StoreEngineException $e ) {
			if ( StoreEngineNotFoundException::WP_ERROR_CODE === $e->get_wp_error_code() ) {
				wp_send_json_error( __( 'Invalid request. Product/Price not found.', 'storeengine' ) );
			}

			wp_send_json_error( $e->getMessage() );
		}
	}

	public function direct_checkout( $payload ) {
		try {
			[
				'price_id'       => $price_id,
				'product_id'     => $product_id,
				'quantity'       => $quantity,
				'variation_id'   => $variation_id,
				'variation_data' => $variation_data,
			] = $this->validate_add_to_cart( $payload );

			Helper::cart()->clear_cart();

			$result = Helper::cart()->add_product_to_cart( $price_id, $quantity, $variation_id, $variation_data );

			if ( is_wp_error( $result ) ) {
				wp_send_json_error( $result->get_error_message() );
			}

			do_action( 'storeengine/ajax/cart/added_to_cart', $payload );

			wp_send_json_success( $this->add_to_cart_response( $product_id, $price_id, true ) );
		} catch ( StoreEngineException $e ) {
			if ( StoreEngineNotFoundException::WP_ERROR_CODE === $e->get_wp_error_code() ) {
				wp_send_json_error( __( 'Invalid request. Product/Price not found.', 'storeengine' ) );
			}

			wp_send_json_error( $e->getMessage() );
		}
	}

	protected function remove_cart_item( $payload ) {
		if ( empty( $payload['item_key'] ) ) {
			wp_send_json_error( esc_html__( 'Item key is required.', 'storeengine' ) );
		}

		$item = Helper::cart()->get_cart_item( $payload['item_key'] );

		if ( ! $item ) {
			wp_send_json_error( esc_html__( 'Cart item not found.', 'storeengine' ), 404 );
		}

		$product = Helper::get_product( $item->product_id );

		$item_removed_title = $product ? $product->get_name() : ( $item->name ?: '' );
		/* translators: %s: Item name. */
		$item_removed_title = $item_removed_title ? sprintf( _x( '&ldquo;%s&rdquo;', 'Item name in quotes', 'storeengine' ), $item_removed_title ) : __( 'Item', 'storeengine' );
		$removed_notice     = sprintf(
		/* translators: %s Product title. */
			__( '%s removed from your cart.', 'storeengine' ),
			apply_filters( 'storeengine/cart/item_removed_title', $item_removed_title, $item )
		);

		if ( Helper::cart()->remove_cart_item( $payload['item_key'] ) ) {
			wp_send_json_success( [
				'item'       => $item,
				'product_id' => $item->product_id,
				'price_id'   => $item->price_id,
				'message'    => $removed_notice,
			] );
		}

		wp_send_json_error( esc_html__( 'Failed to remove item from cart.', 'storeengine' ) );
	}

	protected function update_cart_item_quantity( $payload ) {
		if ( empty( $payload['item_key'] ) ) {
			wp_send_json_error( esc_html__( 'Invalid request.', 'storeengine' ) );
		}

		if ( ! array_key_exists( 'quantity', $payload ) ) {
			wp_send_json_error( esc_html__( 'Quantity missing.', 'storeengine' ) );
		}

		$result = Helper::cart()->update_quantity( $payload['item_key'], $payload['quantity'] ?? 1 );

		if ( is_wp_error( $result ) ) {
			wp_send_json_error( $result->get_error_message() );
		}

		$item    = Helper::cart()->get_cart_item( $payload['item_key'] );
		$product = Helper::get_product( $item->product_id );

		$item_updated_title = $product ? $product->get_name() : ( $item->name ?: '' );
		/* translators: %s: Item name. */
		$item_updated_title = $item_updated_title ? sprintf( _x( '&ldquo;%s&rdquo;', 'Item name in quotes', 'storeengine' ), $item_updated_title ) : __( 'Item', 'storeengine' );
		$updated_notice     = sprintf(
		/* translators: %s Product title. */
			__( '%s updated in your cart.', 'storeengine' ),
			apply_filters( 'storeengine/cart/item_updated_title', $item_updated_title, $item )
		);

		wp_send_json_success( [
			'item'       => $item,
			'product_id' => $item->product_id,
			'price_id'   => $item->price_id,
			'message'    => $updated_notice,
		] );
	}

	public function clear_cart() {
		$cart_data = Helper::cart()->get_cart_items();
		Helper::cart()->clear_cart();
		wp_send_json_success( $cart_data );
	}

	protected function refresh_cart() {
		define( 'STOREENGINE_CART', true );
		set_query_var( 'order_pay', 'false' );

		$shortcodes = apply_filters( 'storeengine/cart/refresh_shortcodes', [
			'storeengine-order-summary-shortcode'        => '[storeengine_order_summary]',
			'storeengine-cart-sub-total-table-shortcode' => '[storeengine_cart_sub_total_table]',
		] );

		$fragments = array_map( fn( $shortcode ) => do_shortcode( $shortcode ), $shortcodes );

		ob_start();
		storeengine_checkout_payment_method();
		$fragments['storeengine-ajax-checkout-form__payments'] = ob_get_clean();

		wp_send_json_success( $fragments );
	}
}
