<?php
/**
 * Checks the importability of an item.
 *
 * @package EaLab\WP_Deployer
 */

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

/**
 * Requires.
 */
require_once __DIR__ . '/component-based-object.php';

use EaLab\WP_Deployer\vendor\Ealab\Deployer\Exception\WpDeployException;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Import\Importability;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Tracking\TrackingManager;

/**
 * Checks if the item can be imported in the production instance.
 *
 * @param array<string,mixed> $deployment_items The deployment items, indexed by the full UUID.
 * @param array               $context The configuration. Must contain the following keys:
 *     - "context", string: The context of the check.
 *
 * @return array<string,int> Contains the bitwise result of the importability check, keyed by the item full UUID.
 *   See Importability::* constants.
 *   When exporting, the most important and relevant one is CAN_IMPORT.
 *   Note: even if the item is not "importable", it will still be exported.
 *   In this case, the user will have to perform the merge on the production instance.
 *
 * @throws WpDeployException Error on build.
 */
function deploy_sync_content__check_importability( array $deployment_items, array $context = array() ): array {
	if ( empty( $context['form_context'] ) ) {
		throw new WpDeployException( 'Missing context.' );
	}

	$tracking_manager = deploy_sync_content__get_root_cbo( TrackingManager::class );

	if ( empty( $tracking_manager ) ) {
		throw new WpDeployException( 'Cannot check importability: tracking manager not found.' );
	}

	if ( 'export' === $context['form_context'] ) {
		if ( $tracking_manager->isProductionEnvironment() ) {
			// We are already on the production instance, so we don't need to check anything for export;
			// export is always available.
			array_walk(
				$deployment_items,
				function ( &$val ) {
					// This will build the value for each item.
					$val = Importability::ABORTED_CHECK;
				}
			);

			return $deployment_items;
		}

		try {
			// Check the importability from the production instance point of view.
			return $tracking_manager->checkImportability( $deployment_items, array( 'against_prod' => true ) );
		} catch ( WpDeployException $e ) {
			// The production instance is not available.
			// We can still export, but the user will have to perform the merge on the production instance.
			// Set the state to limit further checks.
			$context['build_state']->ignore_production_checks = true;

			switch ( $e->getCode() ) {
				case 413:
					$error_message = esc_html__( 'The production server refused to check the item statuses because the transfer size limit was reached. The production server\'s upload size limits must be raised if you want to deploy this bundle on it through the web transfer service.', 'deploy-sync-content' );
					break;

				default:
					break;
			}

			if ( ! empty( $error_message ) ) {
				deploy_sync_content__error_notice( $error_message );
			}

			array_walk(
				$deployment_items,
				function ( &$val ) {
					// This will build the value for each item.
					$val = Importability::UNREACHABLE_PRODUCTION_INSTANCE;
				}
			);

			return $deployment_items;
		}
	}

	if ( 'import' === $context['form_context'] ) {
		// Check the result on the current instance.
		return $tracking_manager->checkImportability( $deployment_items );
	}

	throw new WpDeployException( 'Cannot check importability: unknown context.' );
}
