<?php
/**
 * Handles the transmutation of delimited strings by splitting, processing each segment with a sub-handler, and rejoining.
 *
 * @package Ealab\Deployer
 */

namespace Ealab\Deployer\Tracking\ItemValueHandler\ValueProcessor\TransmutationHandler;

use Dakwamine\Component\ComponentBasedObject;
use Dakwamine\Component\Exception\UnmetDependencyException;
use Ealab\Deployer\Exception\IgnoredTransmutationException;
use Ealab\Deployer\Exception\WpDeployException;
use Symfony\Component\Yaml\Yaml;

/**
 * Handles the transmutation of delimited strings by splitting, processing each segment with a sub-handler, and rejoining.
 */
class DelimitedTransmutationHandler extends TransmutationHandlerBase {
	/**
	 * {@inheritDoc}
	 */
	public static function getFormBuild(): ?array {
		$raw_build = <<<YAML
		separator:
		  label:
		    load: field_label
		    content: Separator
		  field:
		    type: TextField
		    dataLocation: ~.transmutation_handler_options.separator
		    defaultValue: ","
		trim:
		  label:
		    load: field_label
		    content: Trim whitespace
		  field:
		    type: CheckBoxField
		    dataLocation: ~.transmutation_handler_options.trim
		    multiple: false
		    options:
		      - label: "Trim whitespace"
		        value: true
		    defaultFieldValue: true
		warning:
		  type: div
		  attributes:
		    style:
		      backgroundColor: "#fff3cd"
		      border: "1px solid #ffc107"
		      borderRadius: "5px"
		      padding: "10px"
		      marginTop: "10px"
		      marginBottom: "10px"
		  content:
		    - type: div
		      attributes:
		        style:
		          fontWeight: "bold"
		          marginBottom: "5px"
		      content: "⚠️ Incomplete Implementation"
		    - type: div
		      content: "The sub-handler configuration form is not yet fully implemented. Editing and saving this configuration through the UI may break the existing configuration. Please edit the configuration manually in the JSON file."
		YAML;

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

		$build['separator']['label']['content'] = __( 'Separator', 'deploy-sync-content' );
		$build['trim']['label']['content']      = __( 'Trim whitespace', 'deploy-sync-content' );
		$build['warning']['content'][0]['content'] = __( '⚠️ Incomplete Implementation', 'deploy-sync-content' );
		$build['warning']['content'][1]['content'] = __( 'The sub-handler configuration form is not yet fully implemented. Editing and saving this configuration through the UI may break the existing configuration. Please edit the configuration manually in the JSON file.', 'deploy-sync-content' );

		return $build;
	}

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

	/**
	 * {@inheritDoc}
	 */
	static public function getPublicName(): string {
		return _dpgettext( 'deployer-core', 'Transmutation handler public name', 'Delimited (Split/Join)' );
	}

	/**
	 * Processes a delimited string by splitting it, processing each segment with a sub-handler, and rejoining.
	 *
	 * @param mixed      $value The value to process.
	 * @param array|null $options The options to use for the transmutation.
	 * @param string     $operation The operation to perform ('toExport', 'toImportPresave', or 'toImportFinalize').
	 *
	 * @return string The processed value.
	 *
	 * @throws IgnoredTransmutationException If the value is not a string.
	 * @throws WpDeployException If the sub-handler configuration is invalid or processing fails.
	 */
	private function processDelimited( $value, ?array $options, string $operation ): string {
		if ( ! is_string( $value ) ) {
			throw new IgnoredTransmutationException();
		}

		$separator        = $options['separator'] ?? ',';
		$trim             = $options['trim'] ?? true;
		$sub_handler_config = $options['sub_handler'] ?? null;

		if ( ! $sub_handler_config || ! isset( $sub_handler_config['transmutation_handler'] ) ) {
			throw new WpDeployException( 'Sub-handler configuration is required for delimited transmutation handler.' );
		}

		// Same structure as transmutation processor
		// { transmutation_handler: "reference", transmutation_handler_options: {...}, data_walker_pattern: "..." }
		$sub_handler_id = $sub_handler_config['transmutation_handler'];
		$sub_handler_options = $sub_handler_config['transmutation_handler_options'] ?? array();
		$sub_handler_data_walker_pattern = $sub_handler_config['data_walker_pattern'] ?? null;

		// Split the string.
		$segments = explode( $separator, $value );

		// Process each segment.
		$processed_segments = array();

		try {
			// Get the sub-handler class.
			$sub_handler_class = TransmutationHandlerManager::getClassById( $sub_handler_id );

			/** @var TransmutationHandlerBase $sub_handler */
			$sub_handler = $this->getComponentByClassName( $sub_handler_class, true );

			if ( ! $sub_handler instanceof TransmutationHandlerBase ) {
				throw new WpDeployException( 'Invalid sub-handler class for delimited transmutation handler.' );
			}

			// Merge sub-handler options with context options.
			$final_sub_handler_options = array_merge(
				$sub_handler_options,
				array(
					'_value_processor'    => $options['_value_processor'] ?? null,
					'_item_value_handler' => $options['_item_value_handler'] ?? null,
				)
			);

			foreach ( $segments as $segment ) {
				if ( $trim ) {
					$segment = trim( $segment );
				}

				// Preserve empty segments.
				if ( '' === $segment ) {
					$processed_segments[] = $segment;
					continue;
				}

				// Process the segment with the sub-handler.
				try {
					switch ( $operation ) {
						case 'toExport':
							$processed_segment = $sub_handler->toExport( $segment, $final_sub_handler_options );
							break;

						case 'toImportPresave':
							$processed_segment = $sub_handler->toImportPresave( $segment, $final_sub_handler_options );
							break;

						case 'toImportFinalize':
							$processed_segment = $sub_handler->toImportFinalize( $segment, $final_sub_handler_options );
							break;

						default:
							throw new WpDeployException( sprintf( 'Unknown operation: %s', $operation ) );
					}

					$processed_segments[] = $processed_segment;
				} catch ( IgnoredTransmutationException $e ) {
					// If sub-handler ignores, keep original segment.
					$processed_segments[] = $segment;
				}
				// Other exceptions (like WpDeployException) will propagate, causing the processor to fail.
			}
		} catch ( UnmetDependencyException $e ) {
			// The sub-handler class is not available. We cannot transmute the value.
			throw new WpDeployException( 'The sub-handler for delimited transmutation handler is not available.' );
		}

		// Reconcatenate.
		return implode( $separator, $processed_segments );
	}

	/**
	 * {@inheritDoc}
	 */
	public function toExport( $value, ?array $options = array() ) {
		return $this->processDelimited( $value, $options, 'toExport' );
	}

	/**
	 * {@inheritDoc}
	 */
	public function toImportPresave( $value, ?array $options = array() ) {
		return $this->processDelimited( $value, $options, 'toImportPresave' );
	}

	/**
	 * {@inheritDoc}
	 */
	public function toImportFinalize( $value, ?array $options = array() ) {
		return $this->processDelimited( $value, $options, 'toImportFinalize' );
	}
}
