<?php

namespace ElementPack\Modules\ImageMasking\Normalizers;

use ElementPack\Modules\ImageMasking\Atomic\Support;

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

class Settings_Normalizer {
	private const POSITION_MAP = [
		'center-center' => 'center center',
		'center-left'   => 'center left',
		'center-right'  => 'center right',
		'top-center'    => 'top center',
		'top-left'      => 'top left',
		'top-right'     => 'top right',
		'bottom-center' => 'bottom center',
		'bottom-left'   => 'bottom left',
		'bottom-right'  => 'bottom right',
	];

	private const REPEAT_MAP = [
		'repeat'          => 'repeat',
		'repeat-x'        => 'repeat-x',
		'repeat-y'        => 'repeat-y',
		'space'           => 'space',
		'round'           => 'round',
		'no-repeat'       => 'no-repeat',
		'repeat-space'    => 'repeat space',
		'round-space'     => 'round space',
		'no-repeat-round' => 'no-repeat round',
	];

	public function normalize( $widget ) {
		$atomic_settings = $this->normalize_atomic_settings( $widget );

		if ( $atomic_settings ) {
			return $atomic_settings;
		}

		return $this->normalize_legacy_settings( $widget );
	}

	private function normalize_atomic_settings( $widget ) {
		$candidates = [];

		if ( method_exists( $widget, 'get_data' ) ) {
			try {
				$raw_settings = $widget->get_data( 'settings' );
			} catch ( \Throwable $e ) {
				$raw_settings = null;
			}

			if ( is_array( $raw_settings ) ) {
				$candidates[] = $raw_settings;
			}
		}

		if ( method_exists( $widget, 'get_atomic_setting' ) ) {
			$candidates[] = [
				Support::ACTIVE_KEY => $this->get_atomic_setting( $widget, Support::ACTIVE_KEY ),
				Support::SHAPE_KEY => $this->get_atomic_setting( $widget, Support::SHAPE_KEY ),
				Support::SHAPE_DEFAULT_KEY => $this->get_atomic_setting( $widget, Support::SHAPE_DEFAULT_KEY ),
				Support::SHAPE_CUSTOM_KEY => $this->get_atomic_setting( $widget, Support::SHAPE_CUSTOM_KEY ),
				Support::POSITION_KEY => $this->get_atomic_setting( $widget, Support::POSITION_KEY ),
				Support::SIZE_KEY => $this->get_atomic_setting( $widget, Support::SIZE_KEY ),
				Support::CUSTOM_SIZE_KEY => $this->get_atomic_setting( $widget, Support::CUSTOM_SIZE_KEY ),
				Support::REPEAT_KEY => $this->get_atomic_setting( $widget, Support::REPEAT_KEY ),
			];
		}

		foreach ( $candidates as $candidate ) {
			$normalized = $this->normalize_settings_array( $candidate, true );

			if ( $normalized ) {
				return $normalized;
			}
		}

		return null;
	}

	private function get_atomic_setting( $widget, string $key ) {
		try {
			return $widget->get_atomic_setting( $key );
		} catch ( \Throwable $e ) {
			return null;
		}
	}

	private function normalize_legacy_settings( $widget ) {
		if ( ! method_exists( $widget, 'get_settings_for_display' ) ) {
			return null;
		}

		$settings = [
			Support::ACTIVE_KEY => $widget->get_settings_for_display( Support::ACTIVE_KEY ),
			Support::SHAPE_KEY => $widget->get_settings_for_display( Support::SHAPE_KEY ),
			Support::SHAPE_DEFAULT_KEY => $widget->get_settings_for_display( Support::SHAPE_DEFAULT_KEY ),
			Support::SHAPE_CUSTOM_KEY => $widget->get_settings_for_display( Support::SHAPE_CUSTOM_KEY ),
			Support::POSITION_KEY => $widget->get_settings_for_display( Support::POSITION_KEY ),
			Support::SIZE_KEY => $widget->get_settings_for_display( Support::SIZE_KEY ),
			Support::CUSTOM_SIZE_KEY => $widget->get_settings_for_display( Support::CUSTOM_SIZE_KEY ),
			Support::REPEAT_KEY => $widget->get_settings_for_display( Support::REPEAT_KEY ),
		];

		return $this->normalize_settings_array( $settings, false );
	}

	private function normalize_settings_array( array $settings, bool $unwrap_transformable ) {
		$active = $this->extract_value( $settings[ Support::ACTIVE_KEY ] ?? null, $unwrap_transformable );

		if ( ! $this->is_truthy( $active ) ) {
			return null;
		}

		$shape_type = $this->string_value( $settings[ Support::SHAPE_KEY ] ?? 'default', $unwrap_transformable, 'default' );
		$default_shape = $this->string_value( $settings[ Support::SHAPE_DEFAULT_KEY ] ?? 'shape-1', $unwrap_transformable, 'shape-1' );
		$mask_url = '';
		$color_overlay_url = '';

		if ( 'custom' === $shape_type ) {
			$mask_url = $this->extract_image_url( $settings[ Support::SHAPE_CUSTOM_KEY ] ?? null, $unwrap_transformable );
		} else {
			$mask_url = BDTEP_ASSETS_URL . 'images/mask/' . sanitize_file_name( $default_shape ) . '.svg';
			$color_overlay_url = element_pack_mask_color_overlay_url( $default_shape );
		}

		if ( '' === $mask_url ) {
			return null;
		}

		$position_key = $this->string_value( $settings[ Support::POSITION_KEY ] ?? 'center-center', $unwrap_transformable, 'center-center' );
		$size_key = $this->string_value( $settings[ Support::SIZE_KEY ] ?? 'contain', $unwrap_transformable, 'contain' );
		$repeat_key = $this->string_value( $settings[ Support::REPEAT_KEY ] ?? 'no-repeat', $unwrap_transformable, 'no-repeat' );

		$mask_size = 'initial' === $size_key
			? $this->format_custom_size( $settings[ Support::CUSTOM_SIZE_KEY ] ?? null, $unwrap_transformable )
			: $size_key;

		$normalized = [
			'active' => 'yes',
			'mask_url' => $mask_url,
			'color_overlay_url' => $color_overlay_url,
			'mask_position' => self::POSITION_MAP[ $position_key ] ?? self::POSITION_MAP['center-center'],
			'mask_size' => $mask_size,
			'mask_repeat' => self::REPEAT_MAP[ $repeat_key ] ?? self::REPEAT_MAP['no-repeat'],
		];

		$normalized['img_style'] = $this->build_img_style( $normalized );
		$normalized['wrapper_style'] = $this->build_wrapper_style( $normalized );

		return $normalized;
	}

	private function build_img_style( array $settings ): string {
		$parts = [
			'-webkit-mask-image: url(' . esc_url( $settings['mask_url'] ) . ')',
			'mask-image: url(' . esc_url( $settings['mask_url'] ) . ')',
			'-webkit-mask-position: ' . $settings['mask_position'],
			'mask-position: ' . $settings['mask_position'],
			'-webkit-mask-size: ' . $settings['mask_size'],
			'mask-size: ' . $settings['mask_size'],
			'-webkit-mask-repeat: ' . $settings['mask_repeat'],
			'mask-repeat: ' . $settings['mask_repeat'],
		];

		return implode( '; ', $parts );
	}

	private function build_wrapper_style( array $settings ): string {
		if ( empty( $settings['color_overlay_url'] ) ) {
			return '';
		}

		return '--bdt-mask-overlay: url(' . esc_url( $settings['color_overlay_url'] ) . ')';
	}

	private function format_custom_size( $value, bool $unwrap_transformable ): string {
		$value = $this->extract_value( $value, $unwrap_transformable );

		if ( is_array( $value ) && isset( $value['size'], $value['unit'] ) ) {
			return $value['size'] . $value['unit'];
		}

		if ( is_array( $value ) && isset( $value['size'] ) ) {
			return (string) $value['size'] . '%';
		}

		return '100%';
	}

	private function extract_image_url( $value, bool $unwrap_transformable, string $image_size = '' ): string {
		$value = $this->extract_value( $value, $unwrap_transformable );
		$image_size = '' !== $image_size ? $image_size : 'full';

		if ( is_array( $value ) ) {
			if ( isset( $value['src'] ) ) {
				$resolved_size = $this->string_value( $value['size'] ?? $image_size, $unwrap_transformable, $image_size );

				return $this->extract_image_url( $value['src'], $unwrap_transformable, $resolved_size );
			}

			$url = $this->extract_value( $value['url'] ?? '', $unwrap_transformable );

			if ( is_string( $url ) && '' !== $url ) {
				return $url;
			}

			$id = absint( $this->extract_value( $value['id'] ?? 0, $unwrap_transformable ) );

			if ( $id ) {
				$attachment_src = wp_get_attachment_image_src( $id, $image_size );

				return is_array( $attachment_src ) ? $attachment_src[0] : '';
			}

			return '';
		}

		return is_string( $value ) ? $value : '';
	}

	private function extract_value( $value, bool $unwrap_transformable ) {
		if ( $unwrap_transformable && is_array( $value ) && array_key_exists( 'value', $value ) ) {
			return $this->extract_value( $value['value'], $unwrap_transformable );
		}

		return $value;
	}

	private function string_value( $value, bool $unwrap_transformable, string $fallback ): string {
		$value = $this->extract_value( $value, $unwrap_transformable );

		return is_string( $value ) && '' !== $value ? $value : $fallback;
	}

	private function is_truthy( $value ): bool {
		return true === $value || 'yes' === $value || 1 === $value || '1' === $value;
	}
}
