<?php
/**
 * PeachPay Square order util class.
 *
 * @package PeachPay
 */

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

require_once PEACHPAY_ABSPATH . '/core/abstract/class-peachpay-order-data.php';

/**
 * Square order metadata utility class for payment details and reusable payment methods.
 */
final class PeachPay_Square_Order_Data extends PeachPay_Order_Data {

	/**
	 * Sets order payment details to be reused. Automatically flags order as containing
	 * a square reusable payment method.
	 *
	 * @param WC_Order    $order woocommerce order to retrieve data from.
	 * @param string      $source_id reusable payment source ID.
	 * @param string      $customer_id square customer ID the source is attached to.
	 * @param string|null $card_id optional Square card-on-file ID (ccof_…).
	 */
	public static function set_reusable_payment_details( $order, $source_id, $customer_id, $card_id = null ) {
		$payment_method_details = array(
			'source_id'   => $source_id,
			'customer_id' => $customer_id,
			'reusable'    => true,
		);

		if ( ! empty( $card_id ) ) {
			$payment_method_details['card_id'] = $card_id;
		}

		self::set_order_metadata( $order, '_pp_square_payment_method_details', $payment_method_details );
	}

	/**
	 * Gets the Square card-on-file ID stored in the order's payment method details.
	 *
	 * @param WC_Order $order woocommerce order to retrieve data from.
	 */
	public static function get_card_on_file_id( $order ): ?string {
		return self::get_order_metadata( $order, '_pp_square_payment_method_details', 'card_id' );
	}

	/**
	 * Gets the _pp_square_payment_method_details order meta.
	 *
	 * @param WC_Order $order woocommerce order to retrieve data from.
	 */
	public static function get_reusable_payment_id( $order ) {
		return self::get_order_metadata( $order, '_pp_square_payment_method_details', 'source_id' );
	}

	/**
	 * Gets the _pp_square_payment_method_details order meta.
	 *
	 * @param WC_Order $order woocommerce order to retrieve data from.
	 */
	public static function get_payment_customer_id( $order ) {
		return self::get_order_metadata( $order, '_pp_square_payment_method_details', 'customer_id' );
	}

	/**
	 * Gets the _pp_square_payment_method_details['reusable'] metadata which tells whether the payment source id
	 * attached to the order has been configured for reuse.
	 *
	 * @param WC_Order $order woocommerce order to retrieve data from.
	 */
	public static function is_payment_reusable( $order ) {
		if ( null === self::get_order_metadata( $order, '_pp_square_payment_method_details', 'reusable' ) ) {
			return false;
		}
		return self::get_order_metadata( $order, '_pp_square_payment_method_details', 'reusable' );
	}

	/**
	 * Stores the Square Payment object details on the order.
	 * Saved fields include: id, status, amount_money, total_money,
	 * processing_fee, refunded_money, refund_ids, source_type,
	 * card_details, etc.
	 *
	 * @param WC_Order $order A WooCommerce order.
	 * @param array    $payment_details The Square Payment object array.
	 * @return boolean Indicating if successful.
	 */
	public static function set_payment_details( $order, $payment_details ) {
		$result = self::set_order_metadata( $order, '_pp_square_payment_details', $payment_details );

		if ( isset( $payment_details['id'] ) && ! empty( $payment_details['id'] ) ) {
			$order->update_meta_data( '_pp_square_payment_id', $payment_details['id'] );
			$order->save_meta_data();
		}

		return $result;
	}

	/**
	 * Gets a specific field from the stored Square Payment details.
	 *
	 * @param WC_Order $order A WooCommerce order.
	 * @param string   $key The field key (e.g. 'id', 'status', 'processing_fee').
	 * @return mixed|null The value or null.
	 */
	public static function get_payment( $order, $key ) {
		return self::get_order_metadata( $order, '_pp_square_payment_details', $key );
	}

	/**
	 * Gets the total processing fees for a Square payment.
	 * Square returns processing_fee as an array of fee objects,
	 * each with amount_money.amount (in smallest currency unit).
	 *
	 * @param WC_Order $order A WooCommerce order.
	 * @return int|null Total fees in smallest currency unit, or null if no data.
	 */
	public static function total_fees( $order ) {
		$processing_fees = self::get_payment( $order, 'processing_fee' );
		if ( null === $processing_fees || ! is_array( $processing_fees ) ) {
			return null;
		}

		$total = 0;
		foreach ( $processing_fees as $fee ) {
			if ( isset( $fee['amount_money']['amount'] ) ) {
				$total += absint( $fee['amount_money']['amount'] );
			}
		}

		return $total;
	}

	/**
	 * Gets the net payout for a Square payment (total - fees - refunds).
	 *
	 * @param WC_Order $order A WooCommerce order.
	 * @return int|null Net payout in smallest currency unit, or null if no data.
	 */
	public static function total_payout( $order ) {
		$total_money = self::get_payment( $order, 'total_money' );
		if ( null === $total_money || ! isset( $total_money['amount'] ) ) {
			return null;
		}

		$gross = intval( $total_money['amount'] );

		$fees = self::total_fees( $order );
		if ( null !== $fees ) {
			$gross -= $fees;
		}

		$refunds = self::total_refunds( $order );
		$gross  -= $refunds;

		return $gross;
	}

	/**
	 * Gets the total refunded amount for a Square payment.
	 *
	 * @param WC_Order $order A WooCommerce order.
	 * @return int Total refunds in smallest currency unit (0 if none).
	 */
	public static function total_refunds( $order ) {
		$refunded_money = self::get_payment( $order, 'refunded_money' );
		if ( null === $refunded_money || ! isset( $refunded_money['amount'] ) ) {
			return 0;
		}

		return absint( $refunded_money['amount'] );
	}

	/**
	 * Gets the list of Square refund IDs that were initiated via WooCommerce.
	 *
	 * @param WC_Order $order A WooCommerce order.
	 * @return array Array of refund ID strings, or empty array on miss or decode failure.
	 */
	public static function get_wc_initiated_refund_ids( WC_Order $order ): array {
		$raw = $order->get_meta( '_pp_square_refund_ids', true );
		if ( empty( $raw ) ) {
			return array();
		}

		$decoded = json_decode( $raw, true );
		if ( ! is_array( $decoded ) ) {
			return array();
		}

		return $decoded;
	}

	/**
	 * Appends a Square refund ID to the list of WooCommerce-initiated refund IDs on the order.
	 *
	 * @param WC_Order $order     A WooCommerce order.
	 * @param string   $refund_id The Square refund ID to record.
	 */
	public static function add_wc_initiated_refund_id( WC_Order $order, string $refund_id ): void {
		$ids   = self::get_wc_initiated_refund_ids( $order );
		$ids[] = $refund_id;
		$order->update_meta_data( '_pp_square_refund_ids', wp_json_encode( $ids ) );
		$order->save_meta_data();
	}
}
