<?php

namespace ElementPack\Modules\ScrollFillEffect\Normalizers;

use ElementPack\Modules\ScrollFillEffect\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::ANIMATION_TYPE_KEY => $this->get_atomic_setting( $widget, Support::ANIMATION_TYPE_KEY ),
				Support::BASE_COLOR_KEY => $this->get_atomic_setting( $widget, Support::BASE_COLOR_KEY ),
				Support::FILL_BG_KEY => $this->get_atomic_setting( $widget, Support::FILL_BG_KEY ),
				Support::FILL_BG_START_COLOR_KEY => $this->get_atomic_setting( $widget, Support::FILL_BG_START_COLOR_KEY ),
				Support::FILL_BG_END_COLOR_KEY => $this->get_atomic_setting( $widget, Support::FILL_BG_END_COLOR_KEY ),
				Support::FILL_BG_ANGLE_KEY => $this->get_atomic_setting( $widget, Support::FILL_BG_ANGLE_KEY ),
				Support::SG_START_SCALE_KEY => $this->get_atomic_setting( $widget, Support::SG_START_SCALE_KEY ),
				Support::SG_END_SCALE_KEY => $this->get_atomic_setting( $widget, Support::SG_END_SCALE_KEY ),
				Support::SG_START_OPACITY_KEY => $this->get_atomic_setting( $widget, Support::SG_START_OPACITY_KEY ),
				Support::SG_END_OPACITY_KEY => $this->get_atomic_setting( $widget, Support::SG_END_OPACITY_KEY ),
				Support::SG_START_COLOR_KEY => $this->get_atomic_setting( $widget, Support::SG_START_COLOR_KEY ),
				Support::SG_END_COLOR_KEY => $this->get_atomic_setting( $widget, Support::SG_END_COLOR_KEY ),
				Support::SG_STAGGER_KEY => $this->get_atomic_setting( $widget, Support::SG_STAGGER_KEY ),
				Support::SG_DURATION_KEY => $this->get_atomic_setting( $widget, Support::SG_DURATION_KEY ),
				Support::SG_START_TRIGGER_KEY => $this->get_atomic_setting( $widget, Support::SG_START_TRIGGER_KEY ),
				Support::SG_END_TRIGGER_KEY => $this->get_atomic_setting( $widget, Support::SG_END_TRIGGER_KEY ),
				Support::RGM_MASK_COLOR_KEY => $this->get_atomic_setting( $widget, Support::RGM_MASK_COLOR_KEY ),
				Support::RGM_X_PERCENT_KEY => $this->get_atomic_setting( $widget, Support::RGM_X_PERCENT_KEY ),
				Support::RGM_START_TRIGGER_KEY => $this->get_atomic_setting( $widget, Support::RGM_START_TRIGGER_KEY ),
				Support::RGM_END_TRIGGER_KEY => $this->get_atomic_setting( $widget, Support::RGM_END_TRIGGER_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::ANIMATION_TYPE_KEY => $widget->get_settings_for_display( Support::ANIMATION_TYPE_KEY ),
			Support::BASE_COLOR_KEY => $widget->get_settings_for_display( Support::BASE_COLOR_KEY ),
			Support::FILL_BG_KEY => $widget->get_settings_for_display( Support::FILL_BG_KEY ),
			Support::FILL_BG_START_COLOR_KEY => $widget->get_settings_for_display( Support::FILL_BG_START_COLOR_KEY ),
			Support::FILL_BG_END_COLOR_KEY => $widget->get_settings_for_display( Support::FILL_BG_END_COLOR_KEY ),
			Support::FILL_BG_ANGLE_KEY => $widget->get_settings_for_display( Support::FILL_BG_ANGLE_KEY ),
			Support::SG_START_SCALE_KEY => $widget->get_settings_for_display( Support::SG_START_SCALE_KEY ),
			Support::SG_END_SCALE_KEY => $widget->get_settings_for_display( Support::SG_END_SCALE_KEY ),
			Support::SG_START_OPACITY_KEY => $widget->get_settings_for_display( Support::SG_START_OPACITY_KEY ),
			Support::SG_END_OPACITY_KEY => $widget->get_settings_for_display( Support::SG_END_OPACITY_KEY ),
			Support::SG_START_COLOR_KEY => $widget->get_settings_for_display( Support::SG_START_COLOR_KEY ),
			Support::SG_END_COLOR_KEY => $widget->get_settings_for_display( Support::SG_END_COLOR_KEY ),
			Support::SG_STAGGER_KEY => $widget->get_settings_for_display( Support::SG_STAGGER_KEY ),
			Support::SG_DURATION_KEY => $widget->get_settings_for_display( Support::SG_DURATION_KEY ),
			Support::SG_START_TRIGGER_KEY => $widget->get_settings_for_display( Support::SG_START_TRIGGER_KEY ),
			Support::SG_END_TRIGGER_KEY => $widget->get_settings_for_display( Support::SG_END_TRIGGER_KEY ),
			Support::RGM_MASK_COLOR_KEY => $widget->get_settings_for_display( Support::RGM_MASK_COLOR_KEY ),
			Support::RGM_X_PERCENT_KEY => $widget->get_settings_for_display( Support::RGM_X_PERCENT_KEY ),
			Support::RGM_START_TRIGGER_KEY => $widget->get_settings_for_display( Support::RGM_START_TRIGGER_KEY ),
			Support::RGM_END_TRIGGER_KEY => $widget->get_settings_for_display( Support::RGM_END_TRIGGER_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 [
			'enable' => 'yes',
			'animation_type' => $this->string_value( $settings[ Support::ANIMATION_TYPE_KEY ] ?? 'scroll_fill', $unwrap_transformable, 'scroll_fill' ),
			'base_color' => $this->string_value( $settings[ Support::BASE_COLOR_KEY ] ?? 'rgba(156, 156, 156, 0.5)', $unwrap_transformable, 'rgba(156, 156, 156, 0.5)' ),
			'fill_bg' => $this->normalize_fill_background( $settings, $unwrap_transformable ),
			'sg_start_scale' => [ 'size' => $this->float_value( $settings[ Support::SG_START_SCALE_KEY ] ?? 2, $unwrap_transformable, 2 ) ],
			'sg_end_scale' => [ 'size' => $this->float_value( $settings[ Support::SG_END_SCALE_KEY ] ?? 1, $unwrap_transformable, 1 ) ],
			'sg_start_opacity' => [ 'size' => $this->float_value( $settings[ Support::SG_START_OPACITY_KEY ] ?? 0, $unwrap_transformable, 0 ) ],
			'sg_end_opacity' => [ 'size' => $this->float_value( $settings[ Support::SG_END_OPACITY_KEY ] ?? 1, $unwrap_transformable, 1 ) ],
			'sg_start_color' => $this->string_value( $settings[ Support::SG_START_COLOR_KEY ] ?? '#00e239', $unwrap_transformable, '#00e239' ),
			'sg_end_color' => $this->string_value( $settings[ Support::SG_END_COLOR_KEY ] ?? '#ffffff', $unwrap_transformable, '#ffffff' ),
			'sg_stagger' => [ 'size' => $this->float_value( $settings[ Support::SG_STAGGER_KEY ] ?? 0.1, $unwrap_transformable, 0.1 ) ],
			'sg_duration' => [ 'size' => $this->float_value( $settings[ Support::SG_DURATION_KEY ] ?? 1.5, $unwrap_transformable, 1.5 ) ],
			'sg_start_trigger' => $this->string_value( $settings[ Support::SG_START_TRIGGER_KEY ] ?? 'top 80%', $unwrap_transformable, 'top 80%' ),
			'sg_end_trigger' => $this->string_value( $settings[ Support::SG_END_TRIGGER_KEY ] ?? 'top 30%', $unwrap_transformable, 'top 30%' ),
			'rgm_mask_color' => $this->string_value( $settings[ Support::RGM_MASK_COLOR_KEY ] ?? '#000000', $unwrap_transformable, '#000000' ),
			'rgm_x_percent' => [ 'size' => $this->float_value( $settings[ Support::RGM_X_PERCENT_KEY ] ?? -100, $unwrap_transformable, -100 ) ],
			'rgm_start_trigger' => $this->string_value( $settings[ Support::RGM_START_TRIGGER_KEY ] ?? 'top 80%', $unwrap_transformable, 'top 80%' ),
			'rgm_end_trigger' => $this->string_value( $settings[ Support::RGM_END_TRIGGER_KEY ] ?? 'top 20%', $unwrap_transformable, 'top 20%' ),
		];
	}

	private function normalize_fill_background( array $settings, bool $unwrap_transformable ): string {
		$fallback = 'linear-gradient(90deg, #08aeec 0%, #2af598 100%)';
		$fill_bg  = $this->string_value( $settings[ Support::FILL_BG_KEY ] ?? '', $unwrap_transformable, '' );

		if ( '' !== $fill_bg ) {
			return $fill_bg;
		}

		$start_color = $this->string_value( $settings[ Support::FILL_BG_START_COLOR_KEY ] ?? '#08aeec', $unwrap_transformable, '#08aeec' );
		$end_color   = $this->string_value( $settings[ Support::FILL_BG_END_COLOR_KEY ] ?? '#2af598', $unwrap_transformable, '#2af598' );
		$angle       = $this->float_value( $settings[ Support::FILL_BG_ANGLE_KEY ] ?? 90, $unwrap_transformable, 90 );

		if ( '' === $start_color || '' === $end_color ) {
			return $fallback;
		}

		return sprintf( 'linear-gradient(%sdeg, %s 0%%, %s 100%%)', $this->format_number( $angle ), $start_color, $end_color );
	}

	private function format_number( float $value ): string {
		return rtrim( rtrim( sprintf( '%.4F', $value ), '0' ), '.' );
	}

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