<?php
/**
 * Register syncers.
 *
 * @package flo-sync
 */

namespace NMFS\Sync;

use NMFS\Shared;

use NMFS\Sync\Items\Article_Availabilities\Sync_Article_Availabilities;
use NMFS\Sync\Items\Articles\Stock\Sync_Stock;
use NMFS\Sync\Items\Articles\Sync_Articles;
use NMFS\Sync\Items\Campaigns\Sets\Sync_Campaign_Sets;
use NMFS\Sync\Items\Campaigns\Sync_Campaigns;
use NMFS\Sync\Items\Groups\Sync_Groups;
use NMFS\Sync\Items\Orders\Models\Order_Model;
use NMFS\Sync\Items\Orders\Models\Order_Refund_Model;
use NMFS\Sync\Items\Orders\Sync_Orders;
use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Modules\Sync\Orders\Models\Order_Base_Model;

defined( 'ABSPATH' ) || exit;

/**
 * Class Syncers
 */
class Syncers {

	public const SYNCER_KEY_GROUP                  = 'group';
	public const SYNCER_KEY_ORDER                  = 'order';
	public const SYNCER_KEY_ARTICLE                = 'article';
	public const SYNCER_KEY_ARTICLE_STOCK          = 'article_stock';
	public const SYNCER_KEY_ARTICLE_AVAILABILITIES = 'article_availabilities';
	public const SYNCER_KEY_CAMPAIGN               = 'campaign';
	public const SYNCER_KEY_CAMPAIGN_SET           = 'campaign_set';


	/**
	 * Setup shared hooks.
	 *
	 * @param string $service_name_underscored The service name in underscored format.
	 *
	 * @return void
	 */
	public static function setup_shared_hooks( string $service_name_underscored ): void {
		add_action(
			'northmill_online_shared_setup_external_syncers_' . $service_name_underscored,
			array( self::class, 'setup' )
		);

		// This is needed for legacy order number storage. See Order_Model::get_hub_order_number_legacy().
		add_action(
			'northmill_online_shared_receipt_order_model_class_' . $service_name_underscored,
			function () {
				return Order_Model::class;
			},
			10,
			0
		);
		add_filter(
			'northmill_online_shared_get_hub_order_number_' . $service_name_underscored,
			array( self::class, 'get_hub_order_number_legacy' ),
			10,
			2
		);

		// This is needed for legacy order number storage. See Order_Refund_Model::get_hub_order_number_legacy().
		add_action(
			'northmill_online_shared_receipt_order_refund_model_class_' . $service_name_underscored,
			function () {
				return Order_Refund_Model::class;
			},
			10,
			0
		);
	}

	/**
	 * Setup additional syncers.
	 *
	 * @return void
	 */
	public static function setup(): void {
		Shared::instance()->sync->setup_syncer(
			self::SYNCER_KEY_GROUP,
			Sync_Groups::class,
			5,
		);

		/**
		 * We have explicitly set the priority to its default value for clarity.
		 *
		 * @noinspection PhpRedundantOptionalArgumentInspection
		 */
		Shared::instance()->sync->setup_syncer(
			self::SYNCER_KEY_ORDER,
			Sync_Orders::class,
			10,
		);

		/**
		 * We have explicitly set the priority to its default value for clarity.
		 *
		 * @noinspection PhpRedundantOptionalArgumentInspection
		 */
		Shared::instance()->sync->setup_syncer(
			self::SYNCER_KEY_ARTICLE,
			Sync_Articles::class,
			10,
		);

		Shared::instance()->sync->setup_syncer(
			self::SYNCER_KEY_ARTICLE_STOCK,
			Sync_Stock::class,
			11,
		);

		Shared::instance()->sync->setup_syncer(
			self::SYNCER_KEY_ARTICLE_AVAILABILITIES,
			Sync_Article_Availabilities::class,
			12,
		);

		Shared::instance()->sync->setup_syncer(
			self::SYNCER_KEY_CAMPAIGN,
			Sync_Campaigns::class,
			20,
		);

		Shared::instance()->sync->setup_syncer(
			self::SYNCER_KEY_CAMPAIGN_SET,
			Sync_Campaign_Sets::class,
			21,
		);
	}

	/**
	 * Get order Hub ID for legacy orders.
	 * TODO: Remove in Sync 5.x.x
	 *
	 * @param string $order_number The order number to filter.
	 * @param int    $wc_order_id The WooCommerce order ID.
	 *
	 * @return string|null
	 */
	public static function get_hub_order_number_legacy( string $order_number, int $wc_order_id ): ?string {
		if ( ! empty( $order_number ) ) {
			return $order_number;
		}

		$order_meta = get_post_meta( $wc_order_id, 'mf_order', true );
		if ( ! empty( $order_meta['mf_order_no'] ) ) {
			return $order_meta['mf_order_no'];
		}

		$value              = null;
		$last_sync_response = get_post_meta( $wc_order_id, Order_Base_Model::META_KEY_LAST_SYNC_RESPONSE, true );

		if ( ! $last_sync_response ) {
			return null;
		}

		if ( is_string( $last_sync_response ) ) {
			$last_sync_response = json_decode( $last_sync_response );

			if ( ! empty( $last_sync_response->list[0]->Order->Number ) ) {
				$value = (string) $last_sync_response->list[0]->Order->Number;
			}
		}

		return $value;
	}
}
