<?php
/**
 * PeachPay Square REST client.
 *
 * @package PeachPay
 */

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

/**
 * Thin authenticated REST client for Square endpoints used by PeachPay.
 */
final class PeachPay_Square_REST_Client {

	/**
	 * Pinned Square API version used for all requests.
	 */
	const SQUARE_VERSION = '2024-12-18';

	/**
	 * Secret token.
	 *
	 * @var string
	 */
	private $secret_key;

	/**
	 * Square mode (test/live).
	 *
	 * @var string
	 */
	private $mode;

	/**
	 * Constructor.
	 *
	 * @param string $secret_key Square access token.
	 * @param string $mode test|live.
	 */
	public function __construct( $secret_key, $mode = 'live' ) {
		$this->secret_key = (string) $secret_key;
		$this->mode       = 'test' === $mode ? 'test' : 'live';
	}

	/**
	 * Issue an authenticated Square request.
	 *
	 * @param string     $method HTTP method.
	 * @param string     $path Endpoint path (e.g. /v2/locations).
	 * @param array|null $body JSON body.
	 * @param string     $idempotency_key Optional idempotency key.
	 * @return array|WP_Error
	 */
	public function request( $method, $path, $body = null, $idempotency_key = '' ) {
		$method = strtoupper( $method );
		$url    = rtrim( $this->base_url(), '/' ) . '/' . ltrim( $path, '/' );

		$headers = array(
			'Authorization' => 'Bearer ' . $this->secret_key,
			'Content-Type'  => 'application/json',
			'Accept'        => 'application/json',
			'Square-Version'=> self::SQUARE_VERSION,
		);

		if ( ! empty( $idempotency_key ) ) {
			$headers['Idempotency-Key'] = $idempotency_key;
		}

		$args = array(
			'method'  => $method,
			'headers' => $headers,
			'timeout' => 30,
		);

		if ( null !== $body ) {
			$args['body'] = wp_json_encode( $body );
		}

		$response = wp_remote_request( $url, $args );

		if ( is_wp_error( $response ) ) {
			if ( class_exists( 'PeachPay_Square_Error' ) ) {
				return new WP_Error( 'square_transport_error', '', PeachPay_Square_Error::from_wp_error( $response ) );
			}

			return $response;
		}

		$status = wp_remote_retrieve_response_code( $response );
		$raw    = wp_remote_retrieve_body( $response );
		$data   = json_decode( $raw, true );

		if ( null === $data && ! empty( $raw ) ) {
			return new WP_Error(
				'square_invalid_json',
				__( 'Square returned malformed JSON.', 'peachpay-for-woocommerce' ),
				array(
					'status'   => absint( $status ),
					'code'     => 'MALFORMED_RESPONSE',
					'category' => 'API_ERROR',
					'detail'   => __( 'Square returned malformed JSON.', 'peachpay-for-woocommerce' ),
				)
			);
		}

		if ( $status < 200 || $status >= 300 ) {
			$normalized = class_exists( 'PeachPay_Square_Error' )
				? PeachPay_Square_Error::from_response( $status, is_array( $data ) ? $data : array() )
				: array(
					'status'   => absint( $status ),
					'code'     => 'square_api_error',
					'category' => 'API_ERROR',
					'detail'   => __( 'Square API request failed.', 'peachpay-for-woocommerce' ),
				);

			return new WP_Error( 'square_api_error', '', $normalized );
		}

		return is_array( $data ) ? $data : array();
	}

	/**
	 * Create payment.
	 */
	public function create_payment( $payload ) {
		return $this->request( 'POST', '/v2/payments', $payload, isset( $payload['idempotency_key'] ) ? $payload['idempotency_key'] : '' );
	}

	/**
	 * Get payment.
	 */
	public function get_payment( $payment_id ) {
		return $this->request( 'GET', '/v2/payments/' . rawurlencode( $payment_id ) );
	}

	/**
	 * Refund payment.
	 */
	public function refund_payment( $payload ) {
		return $this->request( 'POST', '/v2/refunds', $payload, isset( $payload['idempotency_key'] ) ? $payload['idempotency_key'] : '' );
	}

	/**
	 * Get customer.
	 */
	public function get_customer( $customer_id ) {
		return $this->request( 'GET', '/v2/customers/' . rawurlencode( $customer_id ) );
	}

	/**
	 * Create customer.
	 */
	public function create_customer( $payload ) {
		return $this->request( 'POST', '/v2/customers', $payload, isset( $payload['idempotency_key'] ) ? $payload['idempotency_key'] : '' );
	}

	/**
	 * Create card on file.
	 */
	public function create_card( $payload ) {
		return $this->request( 'POST', '/v2/cards', $payload, isset( $payload['idempotency_key'] ) ? $payload['idempotency_key'] : '' );
	}

	/**
	 * List locations.
	 */
	public function list_locations() {
		return $this->request( 'GET', '/v2/locations' );
	}

	/**
	 * Register Apple Pay domain.
	 */
	public function register_apple_pay_domain( $domain ) {
		return $this->request( 'POST', '/v2/apple-pay/domains', array( 'domain_name' => $domain ) );
	}

	/**
	 * Base URL for selected mode.
	 *
	 * @return string
	 */
	private function base_url() {
		return 'test' === $this->mode ? 'https://connect.squareupsandbox.com' : 'https://connect.squareup.com';
	}
}
