<?php
/**
 * Deployment item diff.
 *
 * @package EaLab\WP_Deployer
 */

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

/**
 * Requires.
 */
require_once __DIR__ . '/../../../includes/helpers.php';
require_once __DIR__ . '/../utility/component-based-object.php';
require_once __DIR__ . '/deployment-item--label-from-item.php';
require_once __DIR__ . '/deployment-item--label-and-uuid.php';
require_once __DIR__ . '/field-diff.php';

use EaLab\WP_Deployer\vendor\Ealab\Deployer\Diff\Differ;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Exception\WpDeployException;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Tracking\TrackingManager;

/**
 * Deployment item diff.
 *
 * @param array $item The deployment item.
 * @param array $context Context.
 *
 * @return string Markup.
 *
 * @throws WpDeployException If the Deploy & Sync Content plugin is not ready.
 */
function deploy_sync_content__deployment_item__diff( array $item, array $context ): string {
	$tracking_manager = deploy_sync_content__get_root_cbo( TrackingManager::class );

	if ( empty( $tracking_manager ) ) {
		throw new WpDeployException( esc_html( 'The Deploy & Sync Content plugin is not ready; TrackingManager is not ready.' ) );
	}

	switch ( $context['form_context'] ?? '' ) {
		case 'import':
			// Check against the current state of the database.
			$c = $tracking_manager->getDiff( $item, $context );
			break;

		case 'export':
			if ( $tracking_manager->isProductionEnvironment() ) {
				// We are in production environment. No diff can be made.
				return '<div>' . esc_html__( 'No diff can be made in production environment for export.', 'deploy-sync-content' ) . '</div>';
			}

			try {
				// Call the production environment service.
				$c = $tracking_manager->getDiffWithProd( $item, $context );
			} catch ( WpDeployException $exception ) {
				// Translators: error reason.
				$message = sprintf( esc_html__( 'The production server is not reachable. Reason: %s', 'deploy-sync-content' ), $exception->getMessage() );

				return '<div class="deploy_sync_content__deployment_item__diff">' . $message . '</div>';
			}

			break;

		default:
			// Unknown context. Abort.
			throw new WpDeployException( esc_html( "Unknown context when trying to get the item's diff." ) );
	}

	// Retrieve the screen label of the item.
	$item_full_uuid = deploy_sync_content__get_uuid_from_deployment_item( $item );

	$html = '<div class="deploy_sync_content__deployment_item__diff">';

	// Attach the metadata as hidden fields.
	// This will allow to retrieve the metadata of both sides when the form is submitted.
	$metadata_json_encoded = htmlspecialchars( json_encode( $c['metadata'] ?? array() ) );

	$encoded_item_full_uuid = deploy_sync_content__encode_for_field_name( $item_full_uuid );

	$html .= '<input type="hidden" name="complete_metadata[' . htmlspecialchars( $encoded_item_full_uuid ) . ']" value="' . htmlspecialchars( $metadata_json_encoded ). '" />';

	try {
		switch ( $c['result'] ) {
			case Differ::DIFF_RESULT__ERROR:
				$html .= '<div class="alert alert-danger" role="alert">' . __( 'Error', 'deploy-sync-content' ) . ': ' . esc_html( $c['message'] ) . '</div>';
				break;

			case Differ::DIFF_RESULT__SAME:
				$html .= '<div class="text-center">' . esc_html__( 'The content is identical.', 'deploy-sync-content' ) . '</div>';
				break;
		}

		switch ( $c['result'] ) {
			case Differ::DIFF_RESULT__NEW:
			case Differ::DIFF_RESULT__MODIFIED:
				foreach ( $c['diff'] as $full_field_name => $field_result ) {
					if ( empty( $field_result['html_diff'] ) ) {
						continue;
					}

					$html .= deploy_sync_content__field_diff(
						array_merge(
							$context,
							array( 'full_field_name' => $full_field_name ),
							$field_result
						)
					);
				}
				break;
		}
	} finally {
		$html .= '</div>';

		$context['differ_result']         = $context['differ_result'] ?? new Deploy_Sync_Content__State();
		$context['differ_result']->result = $c['result'];
	}

	return $html;
}
