<?php

namespace WeeConnectPay\Api\Requests;

use WC_Order;
use WeeConnectPay\Dependencies\GuzzleHttp\Exception\GuzzleException;
use WeeConnectPay\Dependencies\Psr\Http\Message\ResponseInterface;
use WeeConnectPay\Api\ApiClient;
use WeeConnectPay\Api\ApiEndpoints;
use WeeConnectPay\WordPress\Plugin\includes\WeeConnectPayUtilities;
use WeeConnectPay\WordPress\Plugin\includes\WeeConnectPayHelper;

class CreateCloverChargeRequest extends ApiClient {

	/**
	 * POST request
	 *
	 * @param bool $capture            Whether to capture the charge immediately (true) or authorize only (false).
	 * @param bool $threeDSecureOptIn  When true, attach a 3-D Secure opt-in marker + browser_info to the request body.
	 * @param array|null $browserInfo  Output of `window._3DSUtil.getBrowserInfo()` from the client, or null. Required by Clover when 3DS is in effect; browser_ip is filled in server-side by the backend.
	 */
	public function POST(string $tokenizedCard, string $ipAddress, ?int $amount, WC_Order $order, bool $capture = false, bool $threeDSecureOptIn = false, ?array $browserInfo = null): ResponseInterface {
		return $this->client->post( ApiEndpoints::createCharge(), self::setOptions($tokenizedCard, $ipAddress, $amount, $order, $capture, $threeDSecureOptIn, $browserInfo));
	}

	/**
	 * @param string $tokenizedCard
	 * @param string $ipAddress
	 * @param int|null $amount
	 * @param bool $capture
	 * @return array
	 * @updated 3.4.0
	 */
	private static function setOptions(string $tokenizedCard, string $ipAddress, ?int $amount, WC_Order $order, bool $capture = false, bool $threeDSecureOptIn = false, ?array $browserInfo = null ): array {
		$options['form_params'] = self::setRequestBody( $tokenizedCard, $ipAddress , $amount, $order, $capture, $threeDSecureOptIn, $browserInfo);

		return $options;
	}

	/**
	 * Set the request body
	 *
	 * @param string $tokenizedCard
	 * @param string $ipAddress
	 * @param int|null $amount
	 * @param bool $capture
	 * @return array
	 */
	private static function setRequestBody(string $tokenizedCard, string $ipAddress, ?int $amount, WC_Order $order, bool $capture = false, bool $threeDSecureOptIn = false, ?array $browserInfo = null): array {
		$order_id = $order->get_id();

		$items_summary_parts = array();
		foreach ( $order->get_items() as $item ) {
			if ( ! $item instanceof \WC_Order_Item_Product ) {
				continue;
			}
			$quantity = (int) $item->get_quantity();
			$name = $item->get_name();
			$items_summary_parts[] = sprintf( '%d X %s', $quantity, $name );
		}
		$items_summary = implode( ', ', $items_summary_parts );

		// Add Customer Data.
		$customer_data = array();
		$user_id       = get_post_meta( $order_id, '_customer_user', true );
		$user          = get_userdata( $user_id );

		$customer_data['email'] = $order->get_billing_email();
		if ( false !== $user ) {
			$customer = new \WC_Customer( $user_id );
			$customer_data['first_name'] = $customer->get_first_name();
			$customer_data['last_name']  = $customer->get_last_name();
			$customer_data['phone']      = $customer->get_billing_phone();
		} else {
			$customer_data['first_name'] = $order->get_billing_first_name();
			$customer_data['last_name']  = $order->get_billing_last_name();
			$customer_data['phone']      = $order->get_billing_phone();
		}
		$customer_data = array_filter( $customer_data ); // Remove empty values.

		// Maximum length of the external reference id is 12 characters.
		$order_id = (string) $order_id;
		if ( strlen( $order_id ) > 12 ) {
			$order_id = substr( $order_id, -12 );
		}

		$params = array(
			'ip_address'            => $ipAddress,
			'integration_version'   => WEECONNECT_VERSION,
			'amount'                => $amount,
			'tokenized_card'        => $tokenizedCard,
			'capture'               => $capture,
			'currency'              => strtolower( $order->get_currency() ),
			'tax_amount'            => $order->get_total_tax() * 100,
			'external_reference_id' => $order_id,
			'description'           => $items_summary,
		);

		if ( ! empty( $customer_data ) ) {
			$params['customer'] = $customer_data;
		}

		if ( $threeDSecureOptIn ) {
			$params['three_d_secure_opt_in'] = true;
			$params['browser_info']          = $browserInfo ?? array();
		}

		return $params;
	}
}
