<?php
/**
 * Square subscription plan helpers (Catalog + WooCommerce product mapping).
 *
 * @package SHC4WC
 */

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

class SHC4WC_Subscriptions {
	const PRODUCT_META_VARIATION_ID = '_shc4wc_square_subscription_variation_id';
	const CACHE_KEY                 = 'shc4wc_subscription_variations';
	const CACHE_TTL                 = 300;

	/**
	 * @return array<int, array{id:string,name:string,cadence:string,amount:float,currency:string,plan_name:string}>
	 */
	public static function get_plan_variations( $force_refresh = false ) {
		if ( ! $force_refresh ) {
			$cached = get_transient( self::CACHE_KEY );
			if ( is_array( $cached ) ) {
				return $cached;
			}
		}

		if ( ! SHC4WC_Plugin::is_connected() ) {
			return array();
		}

		$api        = new SHC4WC_API( SHC4WC_Plugin::get_settings() );
		$variations = array();
		$cursor     = '';
		$related    = array();

		do {
			$response = $api->search_subscription_plan_variations( $cursor );
			if ( is_wp_error( $response ) ) {
				break;
			}

			if ( ! empty( $response['related_objects'] ) && is_array( $response['related_objects'] ) ) {
				foreach ( $response['related_objects'] as $object ) {
					if ( ! empty( $object['id'] ) ) {
						$related[ (string) $object['id'] ] = $object;
					}
				}
			}

			if ( ! empty( $response['objects'] ) && is_array( $response['objects'] ) ) {
				foreach ( $response['objects'] as $object ) {
					$parsed = self::parse_variation_object( $object, $related );
					if ( $parsed ) {
						$variations[] = $parsed;
					}
				}
			}

			$cursor = ! empty( $response['cursor'] ) ? (string) $response['cursor'] : '';
		} while ( '' !== $cursor );

		set_transient( self::CACHE_KEY, $variations, self::CACHE_TTL );

		return $variations;
	}

	/**
	 * @param array<string, mixed> $object  Catalog object.
	 * @param array<string, array> $related Related catalog objects keyed by id.
	 * @return array|null
	 */
	public static function parse_variation_object( array $object, array $related = array() ) {
		if ( empty( $object['id'] ) || empty( $object['subscription_plan_variation_data'] ) ) {
			return null;
		}

		$data   = $object['subscription_plan_variation_data'];
		$name   = ! empty( $data['name'] ) ? (string) $data['name'] : (string) $object['id'];
		$phase  = ! empty( $data['phases'][0] ) && is_array( $data['phases'][0] ) ? $data['phases'][0] : array();
		$cadence = ! empty( $phase['cadence'] ) ? (string) $phase['cadence'] : '';
		$amount  = 0.0;
		$currency = 'USD';

		if ( ! empty( $phase['pricing']['price_money'] ) && is_array( $phase['pricing']['price_money'] ) ) {
			$amount   = ( (int) $phase['pricing']['price_money']['amount'] ) / 100;
			$currency = ! empty( $phase['pricing']['price_money']['currency'] ) ? (string) $phase['pricing']['price_money']['currency'] : 'USD';
		}

		$plan_name = '';
		if ( ! empty( $data['subscription_plan_id'] ) ) {
			$plan_id = (string) $data['subscription_plan_id'];
			if ( ! empty( $related[ $plan_id ]['subscription_plan_data']['name'] ) ) {
				$plan_name = (string) $related[ $plan_id ]['subscription_plan_data']['name'];
			}
		}

		return array(
			'id'        => (string) $object['id'],
			'name'      => $name,
			'cadence'   => $cadence,
			'amount'    => $amount,
			'currency'  => $currency,
			'plan_name' => $plan_name,
		);
	}

	public static function find_variation_by_id( $variation_id ) {
		$variation_id = sanitize_text_field( (string) $variation_id );
		if ( '' === $variation_id ) {
			return null;
		}
		foreach ( self::get_plan_variations() as $variation ) {
			if ( $variation['id'] === $variation_id ) {
				return $variation;
			}
		}
		return null;
	}

	public static function format_variation_label( array $variation ) {
		$parts = array( $variation['name'] );
		if ( $variation['amount'] > 0 ) {
			$parts[] = number_format_i18n( $variation['amount'], 2 ) . ' ' . $variation['currency'];
		}
		if ( '' !== $variation['cadence'] ) {
			$parts[] = strtolower( $variation['cadence'] );
		}
		$parts[] = $variation['id'];
		return implode( ' · ', $parts );
	}

	/**
	 * Square subscription variation id mapped on a WooCommerce product.
	 *
	 * @param WC_Product $product Product.
	 * @return string
	 */
	public static function get_product_variation_id( $product ) {
		if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
			return '';
		}
		return sanitize_text_field( (string) $product->get_meta( self::PRODUCT_META_VARIATION_ID ) );
	}

	/**
	 * First subscription line item on an order that has a Square variation mapped.
	 *
	 * @param WC_Order $order Order.
	 * @return array{variation_id:string,amount:float,name:string}|null
	 */
	public static function get_order_subscription_checkout( $order ) {
		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
			return null;
		}

		foreach ( $order->get_items() as $item ) {
			$product = $item->get_product();
			if ( ! $product ) {
				continue;
			}

			$variation_id = self::get_product_variation_id( $product );
			if ( '' === $variation_id ) {
				continue;
			}

			$catalog = self::find_variation_by_id( $variation_id );
			$amount  = $catalog ? (float) $catalog['amount'] : (float) $item->get_total();
			if ( $amount <= 0 ) {
				$amount = (float) $product->get_price();
			}

			return array(
				'variation_id' => $variation_id,
				'amount'       => $amount,
				'name'         => $item->get_name(),
			);
		}

		return null;
	}

	public static function register_product_fields() {
		if ( ! class_exists( 'WooCommerce' ) ) {
			return;
		}

		add_action( 'woocommerce_product_options_general_product_data', array( __CLASS__, 'render_product_field' ) );
		add_action( 'woocommerce_process_product_meta', array( __CLASS__, 'save_product_field' ) );
		add_action( 'woocommerce_product_after_variable_attributes', array( __CLASS__, 'render_variation_field' ), 10, 3 );
		add_action( 'woocommerce_save_product_variation', array( __CLASS__, 'save_variation_field' ), 10, 2 );
	}

	public static function render_product_field() {
		global $post;
		if ( ! $post ) {
			return;
		}

		$product = wc_get_product( $post->ID );
		if ( ! $product || ! self::product_supports_square_subscription( $product ) ) {
			return;
		}

		self::output_variation_select_field(
			self::PRODUCT_META_VARIATION_ID,
			(string) get_post_meta( $post->ID, self::PRODUCT_META_VARIATION_ID, true )
		);
	}

	public static function save_product_field( $post_id ) {
		if ( ! isset( $_POST['shc4wc_square_subscription_variation_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
			return;
		}
		update_post_meta(
			$post_id,
			self::PRODUCT_META_VARIATION_ID,
			sanitize_text_field( wp_unslash( $_POST['shc4wc_square_subscription_variation_id'] ) ) // phpcs:ignore WordPress.Security.NonceVerification.Missing
		);
	}

	public static function render_variation_field( $loop, $variation_data, $variation ) {
		$product = wc_get_product( $variation->ID );
		if ( ! $product || ! self::product_supports_square_subscription( $product ) ) {
			return;
		}

		echo '<div class="form-row form-row-full">';
		woocommerce_wp_select(
			array(
				'id'            => 'shc4wc_square_subscription_variation_id_' . $loop,
				'name'          => 'shc4wc_square_subscription_variation_id[' . $loop . ']',
				'value'         => get_post_meta( $variation->ID, self::PRODUCT_META_VARIATION_ID, true ),
				'label'         => __( 'Square subscription plan variation', 'payments-connect-square' ),
				'description'   => __( 'Square hosted checkout will subscribe the buyer to this plan variation.', 'payments-connect-square' ),
				'desc_tip'      => true,
				'options'       => self::get_variation_select_options(),
				'wrapper_class' => 'form-row form-row-full',
			)
		);
		echo '</div>';
	}

	public static function save_variation_field( $variation_id, $loop ) {
		if ( ! isset( $_POST['shc4wc_square_subscription_variation_id'][ $loop ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
			return;
		}
		update_post_meta(
			$variation_id,
			self::PRODUCT_META_VARIATION_ID,
			sanitize_text_field( wp_unslash( $_POST['shc4wc_square_subscription_variation_id'][ $loop ] ) ) // phpcs:ignore WordPress.Security.NonceVerification.Missing
		);
	}

	private static function output_variation_select_field( $field_id, $value ) {
		echo '<div class="options_group shc4wc-square-subscription-field">';
		woocommerce_wp_select(
			array(
				'id'          => 'shc4wc_square_subscription_variation_id',
				'value'       => $value,
				'label'       => __( 'Square subscription plan variation', 'payments-connect-square' ),
				'description' => __( 'When set, checkout uses Square Subscription Plan Checkout instead of a one-time payment link.', 'payments-connect-square' ),
				'desc_tip'    => true,
				'options'     => self::get_variation_select_options(),
			)
		);
		echo '</div>';
	}

	/**
	 * @return array<string, string>
	 */
	public static function get_variation_select_options() {
		$options = array(
			'' => __( '— One-time payment (default) —', 'payments-connect-square' ),
		);
		foreach ( self::get_plan_variations() as $variation ) {
			$options[ $variation['id'] ] = self::format_variation_label( $variation );
		}
		return $options;
	}

	private static function product_supports_square_subscription( $product ) {
		if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
			return false;
		}
		if ( function_exists( 'wcs_is_subscription_product' ) && wcs_is_subscription_product( $product ) ) {
			return true;
		}
		return in_array( $product->get_type(), array( 'subscription', 'variable-subscription', 'subscription_variation' ), true );
	}
}
