<?php

namespace HulkPlugins\ElementorPro\Forms\AdvancedFields\Fields;

use Elementor\Controls_Manager;
use Elementor\Repeater;
use ElementorPro\Modules\Forms\Fields\Field_Base;
use ElementorPro\Modules\Forms\Widgets\Form;
use ElementorPro\Plugin;
use HulkPlugins\ElementorPro\Forms\AdvancedFields\Utils\Helper;
use ReflectionClass;
use function HulkPlugins\ElementorPro\Forms\AdvancedFields\hulk_affef_fs;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

abstract class FieldBase extends Field_Base {

	private static int $main_id = 0;
	private string $class_directory;
	protected bool $showContentTab = true;
	protected bool $showStyleTab = true;
	protected bool $showAdvancedTab = true;
	protected bool $showWidgetControls = false;
	private static array $optionalData = [];
	private array $fieldSettings = [];

	public function update_field_control_data( &$control_data ): void {}

	/**
	 * Get current class directory
	 * @return string
	 */
	public function get_class_directory(): string {
		if ( empty( $this->class_directory ) ) {
			$reflection = new ReflectionClass( $this );
			$this->class_directory = dirname( $reflection->getFileName() );
		}
		return $this->class_directory;
	}

	/**
	 * Render field output on the frontend.
	 *
	 * @param array $args
	 * @param array $settings
	 * @param Form $form
	 *
	 * @return void
	 */
	public function render_field( array $args, array &$settings, Form $form ): void {
		foreach ( $args as $key => $value ) {
			$$key = $value;
		}
		require $this->get_class_directory() . DIRECTORY_SEPARATOR . 'render.php';
	}

	/**
	 * Update form field controls.
	 * @param $args
	 *
	 * @return void
	 */
	public function update_field_controls( $args ): void {
		foreach ( $args as $key => $value ) {
			$$key = $value;
		}
		if ( $this->showContentTab ) {
			require $this->get_class_directory() . DIRECTORY_SEPARATOR . 'controls' . DIRECTORY_SEPARATOR . 'content.php';
		}
		if ( $this->showStyleTab ) {
			require $this->get_class_directory() . DIRECTORY_SEPARATOR . 'controls' . DIRECTORY_SEPARATOR . 'style.php';
		}
		if ( $this->showAdvancedTab ) {
			require $this->get_class_directory() . DIRECTORY_SEPARATOR . 'controls' . DIRECTORY_SEPARATOR . 'advanced.php';
		}
	}

	/**
	 * Get main ID
	 * @return int
	 */
	public static function get_main_id(): int {
		if ( empty( self::$main_id ) ) {
			self::$main_id = \Elementor\Plugin::instance()->documents->get_current()->get_main_id();
		}
		return self::$main_id;
	}

	public function kses_allowed_html( $allowed_html ): array {
		return array_merge( $allowed_html, Helper::getAllowedSvgTags() );
	}

	public function optional_data(): array {
		if ( ! self::$optionalData ) {
			self::$optionalData = [
				'restUrl' => rest_url(),
				'nonce'   => wp_create_nonce( 'wp_rest' ),
			];
		}
		return self::$optionalData;
	}

	/**
	 * Field markup
	 * @param $item
	 * @param $item_index
	 * @param $form
	 *
	 * @return void
	 */
	public function render( $item, $item_index, $form ): void {
		$type      = $this->get_type();

		$settings = [];
		$args = [
			'type'       => $type,
			'item'       => $item,
			'prefix'     => $type . '_',
			'item_index' => $item_index,
			'mainId'     => self::get_main_id(),
			'formId'     => $form->get_id(),
			'itemId'     => $item['_id'],
		];

		$args = array_merge( $args, $this->optional_data() );

		$settingsKey = "{$args['prefix']}{$args['mainId']}_{$args['formId']}_{$args['itemId']}";
		$args['key'] = $settingsKey;
		add_filter( 'wp_kses_allowed_html', [ $this,'kses_allowed_html' ] );
		$this->render_field( $args, $settings, $form );
		remove_filter( 'wp_kses_allowed_html', [ $this,'kses_allowed_html' ] );
		if ( $settings ) {
			$settings['freemius']['can_use_premium_code'] = hulk_affef_fs()->can_use_premium_code();
			$settings['freemius']['get_upgrade_url'] = hulk_affef_fs()->get_upgrade_url();
			echo /** @lang text */ "<script id='" . esc_attr( $settingsKey ) . "' type='application/json'>";
			echo wp_json_encode( $settings );
			echo /** @lang text */ '</script>';
		}
	}

	/**
	 * Field controls
	 * @param $widget
	 *
	 * @return void
	 */
	public function update_controls( $widget ): void {
		$elementor = Plugin::elementor();

		$control_data = $elementor->controls_manager->get_control_from_stack( $widget->get_unique_name(), 'form_fields' );

		if ( is_wp_error( $control_data ) ) {
			return;
		}

		$field     = new Repeater();
		$type      = $this->get_type();
		$widget_id = $widget->get_id();

		$args = [
			'type'      => $type,
			'prefix'    => $type . '_',
			'widget_id' => $widget_id,
			'field'     => $field,
		];

		$controls = [];

		if ( $this->showStyleTab ) {
			$controls[ $args['prefix'] . 'form_fields_style_tab' ] = [
				'type'         => 'tab',
				'tab'          => 'content',
				'label'        => esc_attr__( 'Style', 'advanced-fields-for-elementor-forms' ),
				'condition'    =>
					[
						'field_type' => $type,
					],
				'tabs_wrapper' => 'form_fields_tabs',
				'name'         => $args['prefix'] . 'form_fields_style_tab',
			];
		}

		$this->update_field_controls( $args );
		$field_controls = $field->get_controls();
		if ( is_array( $field_controls ) ) {
			$controls = array_merge( $controls, $field_controls );
		}
        if ( isset( $controls['_id'] ) ) {
            unset( $controls['_id'] );
        }
        foreach ( $controls as &$control ) {
			if ( isset( $control['type'] ) && $control['type'] === 'popover_toggle' ) {
		        $control['control_tab'] = 'style';
	        }
	        if ( isset( $control['control_tab'] ) && $control['control_tab'] === Controls_Manager::TAB_CONTENT ) {
	            $control['condition']['field_type'] = $type;
                $control['tab'] = 'content';
                $control['inner_tab'] = 'form_fields_content_tab';
		        $control['tabs_wrapper'] = 'form_fields_tabs';
	        } elseif ( isset( $control['control_tab'] ) && $control['control_tab'] === Controls_Manager::TAB_STYLE ) {
		        $control['condition']['field_type'] = $type;
		        $control['tab'] = 'style';
		        $control['inner_tab'] = $args['prefix'] . 'form_fields_style_tab';
		        $control['tabs_wrapper'] = 'form_fields_tabs';
            } elseif ( isset( $control['control_tab'] ) && $control['control_tab'] === Controls_Manager::TAB_ADVANCED ) {
		        $control['condition']['field_type'] = $type;
		        $control['tab'] = 'advanced';
		        $control['inner_tab'] = 'form_fields_advanced_tab';
		        $control['tabs_wrapper'] = 'form_fields_tabs';
            }
        }
		unset( $control );
		$control_data['fields'] = $this->inject_field_controls( $control_data['fields'], $controls );
		$this->update_field_control_data( $control_data );
		$widget->update_control( 'form_fields', $control_data );
	}

	/**
	 * Enqueue script and style if elementor cache is enabled
	 * @return void
	 */
	public function get_builder_content(): void {
		foreach ( $this->get_style_depends() as $style ) {
			wp_enqueue_style( $style );
		}
		foreach ( $this->get_script_depends() as $script ) {
			wp_enqueue_script( $script );
		}
	}

	/**
	 * Widget style controls
	 *
	 * @param Form $form
	 *
	 * @return void
	 */
	public function widget_style_controls( Form $form ): void {
		if ( $this->showWidgetControls ) {
			$type      = $this->get_type();
			$prefix    = $type . '_';

			require $this->get_class_directory() . '/controls/widget.php';
		}
	}

	/**
	 * Get field settings by ID
	 *
	 * @param array $fields
	 * @param string $id
	 *
	 * @return array|mixed
	 */
	protected function get_field_settings( array $fields, string $id ) {
		if ( empty( $this->fieldSettings[ $id ] ) ) {
			foreach ( $fields as $field ) {
				if ( str_contains( $id, $field['_id'] ) ) {
					$filtered = array_filter(
						$field,
						fn( $key ) => str_starts_with( $key, $this->get_type() ),
						ARRAY_FILTER_USE_KEY
					);
					$result = [];
					foreach ( $filtered as $key => $value ) {
						// Remove the prefix from the key
						$newKey = str_replace( $this->get_type() . '_', '', $key );
						$result[ $newKey ] = $value;
					}
					$this->fieldSettings[ $id ] = $result;
					return $result;
				}
			}
		}
		return $this->fieldSettings[ $id ] ?? [];
	}

	public function doc_notice_control_content( string $url ): string {
		return sprintf(
		// Translators: %s is the documentation link.
			esc_attr__( 'Not sure how to set this? Check our step by step %s.', 'advanced-fields-for-elementor-forms' ),
			/** @lang text */ '<a href="' . esc_url( $url ) . '" target="_blank">' . esc_attr__( 'documentation', 'advanced-fields-for-elementor-forms' ) . '</a>'
		);
	}

	/**
	 * Disabled fields Cleanup controls
	 *
	 * @param $widget
	 *
	 * @return void
	 */
	public function cleanup_controls( $widget ): void {
		$elementor = Plugin::elementor();
		$control_data = $elementor->controls_manager->get_control_from_stack( $widget->get_unique_name(), 'form_fields' );
		if ( is_wp_error( $control_data ) ) {
			return;
		}
		// Remove required control
		if ( isset( $control_data['fields']['required']['conditions']['terms'] ) ) {
			$control_data['fields']['required']['conditions']['terms'][] = [
				'name'     => 'field_type',
				'operator' => '!in',
				'value'    => [ $this->get_type() ],
			];
		}
		$widget->update_control( 'form_fields', $control_data );
	}

	/**
	 * Field constructor.
	 * @return void
	 */
	public function __construct( array $meta ) {
		if ( $meta['isEnabled'] === true ) {
			parent::__construct();
            add_action( 'elementor/frontend/get_builder_content', [ $this,'get_builder_content' ] );
			if ( $this->showWidgetControls ) {
				add_action(
					'elementor/element/form/section_field_style/after_section_end',
					[
						$this,
						'widget_style_controls',
					]
				);
			}
		} else {
            add_action( 'elementor/element/form/section_form_fields/before_section_end', [ $this, 'cleanup_controls' ] );
		}
	}
}
