<?php
/**
 * Handles syncing of article availabilities.
 *
 * @package flo-sync
 */

namespace NMFS\Sync\Items\Article_Availabilities;

use NMFS\Shared;
use NMFS\Sync\Items\Article_Availabilities\Models\Article_Availability_Model;
use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Abstracts\Hub_API\Sync\Abstract_Syncer;
use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Modules\Loggers\Log_Level_Enum;

defined( 'ABSPATH' ) || exit;

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

	/**
	 * Pull articles from API.
	 *
	 * @param array|null $args Arguments to pass to API, or null if no arguments.
	 * @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;
		}

		$article_availabilities = $current_backoffice_account->api->get_article_availabilities( $args );

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

		$not_synced_availabilities = Article_Availabilities::get_all_availabilities();

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

		if ( is_array( $article_availabilities['list'] ) ) {
			foreach ( $article_availabilities['list'] as $availability ) {

				$action = $this->process_pulled_article_availability( $availability );

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

				if (
					! empty( $availability['Id'] ) &&
					isset( $not_synced_availabilities[ $availability['Id'] ] )
				) {
					unset( $not_synced_availabilities[ $availability['Id'] ] );
				}
			}
		}

		if ( ! empty( $not_synced_availabilities ) ) {
			$this->clean_old_availabilities( $not_synced_availabilities );
		}

		return true;
	}

	/**
	 * Process article from API.
	 *
	 * @param array $article_availability Article availability from API.
	 *
	 * @return string|null Action, or null on failure.
	 */
	public function process_pulled_article_availability( array $article_availability ): ?string {
		$article_availability_model = Factory_API::create_availability_from_api( $article_availability );
		Shared::instance()->logger->log(
			'sync',
			'Processing article availability',
			array(
				'name'   => $article_availability_model->name,
				'wp_id'  => $article_availability_model->wp_id ?? null,
				'hub_id' => $article_availability_model->hub_id,
			),
			Log_Level_Enum::DEBUG
		);

		$status = Factory_DB::update_in_db( $article_availability_model );

		Shared::instance()->logger->log(
			'sync',
			'Processed article availability',
			array(
				'name'   => $article_availability_model->name,
				'wp_id'  => $article_availability_model->wp_id,
				'hub_id' => $article_availability_model->hub_id,
			),
			Log_Level_Enum::DEBUG
		);

		return $status['action'];
	}

	/**
	 * Clean article availabilities removed from the API.
	 *
	 * @param Article_Availability_Model[] $old_availabilities Removed availabilities.
	 *
	 * @return void
	 */
	public function clean_old_availabilities( array $old_availabilities ): void {
		foreach ( $old_availabilities as $old_availability ) {
			wp_delete_post( $old_availability->wp_id, true );
		}
	}

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

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

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

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