<?php

namespace ElementPack\Modules\ConfettiEffects\Normalizers;

use ElementPack\Modules\ConfettiEffects\Atomic\Support;

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

class Settings_Normalizer {
	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::TYPE_KEY => $this->get_atomic_setting( $widget, Support::TYPE_KEY ),
				Support::FIREWORKS_DURATION_KEY => $this->get_atomic_setting( $widget, Support::FIREWORKS_DURATION_KEY ),
				Support::ANIM_INFINITE_KEY => $this->get_atomic_setting( $widget, Support::ANIM_INFINITE_KEY ),
				Support::PARTICLE_COUNT_KEY => $this->get_atomic_setting( $widget, Support::PARTICLE_COUNT_KEY ),
				Support::START_VELOCITY_KEY => $this->get_atomic_setting( $widget, Support::START_VELOCITY_KEY ),
				Support::SPREAD_KEY => $this->get_atomic_setting( $widget, Support::SPREAD_KEY ),
				Support::ANGLE_KEY => $this->get_atomic_setting( $widget, Support::ANGLE_KEY ),
				Support::COLORS_KEY => $this->get_atomic_setting( $widget, Support::COLORS_KEY ),
				Support::SHAPE_TYPE_KEY => $this->get_atomic_setting( $widget, Support::SHAPE_TYPE_KEY ),
				Support::SHAPES_KEY => $this->get_atomic_setting( $widget, Support::SHAPES_KEY ),
				Support::SHAPES_EMOJI_KEY => $this->get_atomic_setting( $widget, Support::SHAPES_EMOJI_KEY ),
				Support::SHAPES_SVG_KEY => $this->get_atomic_setting( $widget, Support::SHAPES_SVG_KEY ),
				Support::SCALAR_KEY => $this->get_atomic_setting( $widget, Support::SCALAR_KEY ),
				Support::ORIGIN_KEY => $this->get_atomic_setting( $widget, Support::ORIGIN_KEY ),
				Support::ORIGIN_X_KEY => $this->get_atomic_setting( $widget, Support::ORIGIN_X_KEY ),
				Support::ORIGIN_Y_KEY => $this->get_atomic_setting( $widget, Support::ORIGIN_Y_KEY ),
				Support::TRIGGER_TYPE_KEY => $this->get_atomic_setting( $widget, Support::TRIGGER_TYPE_KEY ),
				Support::TRIGGER_SELECTOR_KEY => $this->get_atomic_setting( $widget, Support::TRIGGER_SELECTOR_KEY ),
				Support::TRIGGER_DELAY_KEY => $this->get_atomic_setting( $widget, Support::TRIGGER_DELAY_KEY ),
				Support::Z_INDEX_KEY => $this->get_atomic_setting( $widget, Support::Z_INDEX_KEY ),
			];
		}

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

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

		return null;
	}

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

		$settings = [];

		foreach ( $this->supported_keys() as $key ) {
			$settings[ $key ] = $widget->get_settings_for_display( $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;
		}

		return [
			Support::ACTIVE_KEY => 'yes',
			Support::TYPE_KEY => $this->string_value( $settings[ Support::TYPE_KEY ] ?? 'basic', $unwrap_transformable, 'basic' ),
			Support::FIREWORKS_DURATION_KEY => [ 'size' => $this->float_value( $settings[ Support::FIREWORKS_DURATION_KEY ] ?? 1500, $unwrap_transformable, 1500 ) ],
			Support::ANIM_INFINITE_KEY => $this->bool_to_yes_no( $settings[ Support::ANIM_INFINITE_KEY ] ?? false, $unwrap_transformable ),
			Support::PARTICLE_COUNT_KEY => [ 'size' => $this->float_value( $settings[ Support::PARTICLE_COUNT_KEY ] ?? 100, $unwrap_transformable, 100 ) ],
			Support::START_VELOCITY_KEY => [ 'size' => $this->float_value( $settings[ Support::START_VELOCITY_KEY ] ?? 45, $unwrap_transformable, 45 ) ],
			Support::SPREAD_KEY => [ 'size' => $this->float_value( $settings[ Support::SPREAD_KEY ] ?? 70, $unwrap_transformable, 70 ) ],
			Support::ANGLE_KEY => [ 'size' => $this->float_value( $settings[ Support::ANGLE_KEY ] ?? 90, $unwrap_transformable, 90 ) ],
			Support::COLORS_KEY => $this->string_value( $settings[ Support::COLORS_KEY ] ?? '', $unwrap_transformable, '' ),
			Support::SHAPE_TYPE_KEY => $this->string_value( $settings[ Support::SHAPE_TYPE_KEY ] ?? 'basic', $unwrap_transformable, 'basic' ),
			Support::SHAPES_KEY => $this->string_value( $settings[ Support::SHAPES_KEY ] ?? 'square|circle', $unwrap_transformable, 'square|circle' ),
			Support::SHAPES_EMOJI_KEY => $this->string_value( $settings[ Support::SHAPES_EMOJI_KEY ] ?? '🎃|🎄|💜', $unwrap_transformable, '🎃|🎄|💜' ),
			Support::SHAPES_SVG_KEY => $this->string_value( $settings[ Support::SHAPES_SVG_KEY ] ?? '', $unwrap_transformable, '' ),
			Support::SCALAR_KEY => [ 'size' => $this->float_value( $settings[ Support::SCALAR_KEY ] ?? 1, $unwrap_transformable, 1 ) ],
			Support::ORIGIN_KEY => $this->bool_to_yes_no( $settings[ Support::ORIGIN_KEY ] ?? false, $unwrap_transformable ),
			Support::ORIGIN_X_KEY => [ 'size' => $this->float_value( $settings[ Support::ORIGIN_X_KEY ] ?? 0.5, $unwrap_transformable, 0.5 ) ],
			Support::ORIGIN_Y_KEY => [ 'size' => $this->float_value( $settings[ Support::ORIGIN_Y_KEY ] ?? 0.6, $unwrap_transformable, 0.6 ) ],
			Support::TRIGGER_TYPE_KEY => $this->string_value( $settings[ Support::TRIGGER_TYPE_KEY ] ?? 'load', $unwrap_transformable, 'load' ),
			Support::TRIGGER_SELECTOR_KEY => $this->string_value( $settings[ Support::TRIGGER_SELECTOR_KEY ] ?? '', $unwrap_transformable, '' ),
			Support::TRIGGER_DELAY_KEY => [ 'size' => $this->float_value( $settings[ Support::TRIGGER_DELAY_KEY ] ?? 3000, $unwrap_transformable, 3000 ) ],
			Support::Z_INDEX_KEY => $this->extract_value( $settings[ Support::Z_INDEX_KEY ] ?? '', $unwrap_transformable ),
		];
	}

	private function supported_keys(): array {
		return [
			Support::ACTIVE_KEY,
			Support::TYPE_KEY,
			Support::FIREWORKS_DURATION_KEY,
			Support::ANIM_INFINITE_KEY,
			Support::PARTICLE_COUNT_KEY,
			Support::START_VELOCITY_KEY,
			Support::SPREAD_KEY,
			Support::ANGLE_KEY,
			Support::COLORS_KEY,
			Support::SHAPE_TYPE_KEY,
			Support::SHAPES_KEY,
			Support::SHAPES_EMOJI_KEY,
			Support::SHAPES_SVG_KEY,
			Support::SCALAR_KEY,
			Support::ORIGIN_KEY,
			Support::ORIGIN_X_KEY,
			Support::ORIGIN_Y_KEY,
			Support::TRIGGER_TYPE_KEY,
			Support::TRIGGER_SELECTOR_KEY,
			Support::TRIGGER_DELAY_KEY,
			Support::Z_INDEX_KEY,
		];
	}

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

	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 is_truthy( $value ): bool {
		return true === $value || 'yes' === $value || 1 === $value || '1' === $value;
	}

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

		if ( is_array( $value ) && isset( $value['size'] ) ) {
			$value = $value['size'];
		}

		return is_numeric( $value ) ? (float) $value : $fallback;
	}

	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 bool_to_yes_no( $value, bool $unwrap_transformable ): string {
		$value = $this->extract_value( $value, $unwrap_transformable );

		return $this->is_truthy( $value ) ? 'yes' : '';
	}
}

