<?php
/**
 * Sync Article Sets to WooCommerce as coupons
 *
 * @package flo-sync
 */

namespace NMFS\Sync\Items\Campaigns\Sets;

use DateInterval;
use DateTime;
use NMFS\Sync\Items\Campaigns\Campaigns;
use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Abstracts\Hub_API\Sync\Abstract_Syncer;

defined( 'ABSPATH' ) || exit;

/**
 * Class Sync
 */
class Sync_Campaign_Sets extends Abstract_Syncer {

	/**
	 * Check if sync is enabled.
	 *
	 * @return bool
	 */
	public function is_enabled(): bool {
		return Campaigns::is_enabled();
	}

	/**
	 * Sync article sets to WooCommerce as coupons
	 *
	 * @param array|null $args Query parameters.
	 * @param bool       $is_first_sync If this sync is the first page of the first Hub account.
	 */
	public function sync( ?array $args = null, bool $is_first_sync = false ): bool {
		$current_backoffice_account = $this->get_current_hub_account();

		if ( ! $current_backoffice_account ) {
			return false;
		}

		$sets = $current_backoffice_account->api->get_article_sets( $args );

		if (
			! isset( $sets['Total'] ) ||
			! isset( $sets['Page'] ) ||
			! isset( $sets['list'] )
		) {
			return false;
		}

		$this->update_status( 'page', $sets['Page'] );
		$this->update_status( 'total', $sets['Total'] );

		if ( is_array( $sets['list'] ) ) {
			$this->process_pulled_sets( $sets['list'] );
		}

		return true;
	}

	/**
	 * Process article sets.
	 *
	 * @param array $api_list List of article sets.
	 */
	public function process_pulled_sets( array $api_list ): void {
		if ( empty( $api_list ) ) {
			return;
		}

		foreach ( $api_list as $set ) {
			if ( empty( $set['ArticleSet'] ) ) {
				continue;
			}

			$action = $this->process_pulled_set( $set['ArticleSet'] );

			if ( $action ) {
				$this->increase_status( $action );
			}
		}
	}

	/**
	 * Process article set.
	 *
	 * @param array $set Article set.
	 *
	 * @return string
	 */
	public function process_pulled_set( array $set ): string {
		$post_type = 'shop_coupon';

		if ( ! $set['IsActive'] ) {
			$deleted = Campaigns::delete_post( $set['ArticleNumber'], $post_type, 'article_set' );

			return $deleted
				? 'delete'
				: 'ignore';
		}

		$post = Campaigns::update_post( $set['ArticleNumber'], $set['ArticleName'], $post_type, 'article_set' );

		if ( ! $post ) {
			return 'error';
		}

		// Add meta.
		update_post_meta( $post, 'discount_type', 'mf_type_set' );
		update_post_meta( $post, 'mf_priority', 0 ); // Sets are always the highest priority.

		$parts = $this->get_parts( $set['articleSetParts'] );
		update_post_meta( $post, 'mf_parts', wp_json_encode( $parts ) );

		update_post_meta(
			$post,
			'mf_end_date',
			( new DateTime() )
				->add( new DateInterval( 'P1Y' ) )
				->format( 'Y-m-d' )
		); // Should always be active.

		update_post_meta( $post, 'mf_last_updated', time() );

		return 'add';
	}

	/**
	 * Get article set parts formatted for store in wp post meta.
	 *
	 * @param mixed $parts From API.
	 *
	 * @return array
	 */
	protected function get_parts( mixed $parts ): array {
		$array = array();

		if ( empty( $parts ) || ! is_array( $parts ) ) {
			return $array;
		}

		foreach ( $parts as $part ) {
			if ( 0 === $part['PartType'] ) {
				// Single SKU.
				$array[] = array(
					'sku'            => $part['ArticleReference'],
					'quantity'       => $part['Quantity'],
					'price_per_unit' => $part['PartPricePerUnit'],
				);
			}
		}

		return $array;
	}

	/**
	 * {@inheritDoc}
	 */
	public function get_display_name(): string {
		return __( 'Campaigns sets', 'flo-sync' );
	}

	/**
	 * {@inheritDoc}
	 */
	public function get_last_synced_wp_option_name(): string {
		return 'mf_sync_campaigns_article_sets_last_updated';
	}

	/**
	 * {@inheritDoc}
	 */
	public function get_last_synced_api_parameter(): ?string {
		return null;
	}
}
