<?php
/**
 * Clears data on import.
 *
 * @package Ealab\Deployer
 */

namespace Ealab\Deployer\Tracking\ItemValueHandler\ValueProcessor;

use Ealab\Deployer\Tracking\ItemValueHandler\ItemValueHandlerBase;
use Ealab\Deployer\Utility\Database;
use Symfony\Component\Yaml\Yaml;

/**
 * Clears data on import.
 */
class ClearDataOnImportProcessor extends ValueProcessorBase {

	/**
	 * {@inheritDoc}
	 */
	public static function getFormBuild(): array {
		$build = parent::getFormBuild();

		$raw_build = <<<YAML
buttons:
  load: processor_item_action_buttons_wrapper
  keepTemplateContext: true
  content:
    - load: processor_item_edit_button
      keepTemplateContext: true
    - load: processor_item_three_action_buttons
      keepTemplateContext: true
modal:
  type: Modal
  attributes:
    style:
      zIndex: 1050 # Modal backdrop fix.
  closeButton: true
  showBoolPath: ~._openEditModal
  headerTitle:
    - Edit this processor
  body:
    allow_non_transient_options:
      field:
        type: CheckBoxField
        dataLocation: ~.allow_non_transient_options
        options:
          - label: Allow non transient options
            value: true
YAML;

		$parsed = Yaml::parse( $raw_build );

		$parsed['modal']['headerTitle'][0] = _dgettext( 'deployer-core', 'Edit this processor' );
		$parsed['modal']['body']['allow_non_transient_options']['field']['options'][0]['label'] = _dgettext( 'deployer-core', 'Allow non transient options' );

		$build[1]['content'] = $parsed;

		return $build;
	}

	/**
	 * {@inheritDoc}
	 */
	public static function getId(): string {
		return 'clear_data_on_import';
	}

	/**
	 * {@inheritDoc}
	 */
	public static function getLabel(): string {
		return _dpgettext( 'deployer-core', 'processor label', 'Clear data on import' );
	}

	/**
	 * {@inheritDoc}
	 */
	public function process( $value, int $operation, ?callable $progress_callback = null ) {
		if ( ItemValueHandlerBase::OPERATION__IMPORT__FINALIZE !== $operation ) {
			return $value;
		}

		$database = Database::getDatabaseHandle();

		$conditions = $this->config['conditions'] ?? array();

		// This is a security feature that requires the user to
		// explicitly allow non-transient options to be deleted.
		$allow_non_transient_options = $this->config['allow_non_transient_options'] ?? false;

		$filtered_conditions = array_filter(
			$conditions,
			function ( $condition ) use ( $allow_non_transient_options ) {
				$tracker     = $condition['tracker'] ?? '';
				$field_name  = $condition['field_name'] ?? '';
				$field_value = $condition['field_value'] ?? '';

				if ( ! $allow_non_transient_options ) {
					if ( 'options' !== $tracker || 'option_name' !== $field_name
						|| '_transient_' !== substr( $field_value, 0, 11 ) ) {
						return false;
					}
				}

				return ! empty( $condition['tracker'] ) && ! empty( $condition['field_name'] ) && ! empty( $condition['field_value'] );
			}
		);

		if ( empty( $filtered_conditions ) ) {
			return $value;
		}

		// Sort by trackers.
		$filtered_conditions = array_reduce(
			$filtered_conditions,
			function ( $carry, $condition ) {
				$tracker = $condition['tracker'];

				if ( ! isset( $carry[ $tracker ] ) ) {
					$carry[ $tracker ] = array();
				}

				$carry[ $tracker ][] = $condition;

				return $carry;
			},
			array()
		);


		foreach ( $filtered_conditions as $tracker => $conditions ) {
			// For each tracker, delete the matching data.
			$table = $database->prefix . $tracker;

			$sql = 'DELETE FROM %i WHERE ';

			$arguments = array( $table );

			$sql_tmp = array();

			foreach ( $conditions as $condition ) {
				$sql_tmp[] = '%i.%i LIKE %s';

				$arguments[] = $table;
				$arguments[] = $condition['field_name'];
				$arguments[] = $condition['field_value'];
			}

			$sql .= implode( ' AND ', $sql_tmp );
			$sql .= ';';

			$database->query( $database->prepare( $sql, $arguments ) );
		}

		return $value;
	}
}
