<?php

namespace SugarCalendarBookings\BookingForm;

use Elementor\Controls_Manager;
use Elementor\Plugin as ElementorPlugin;
use SugarCalendarBookings\Admin\Assets;
use SugarCalendarBookings\Plugin;
use SugarCalendarBookings\Support\ElementorWidgets\AbstractElementorWidget;

/**
 * Booking Form Elementor Widget.
 *
 * @since 1.0.0
 */
class BookingFormElementorWidget extends AbstractElementorWidget {

	/**
	 * Get widget name.
	 *
	 * @since 1.0.0
	 *
	 * @return string
	 */
	public function get_name(): string {

		return 'sugar_calendar_booking_form';
	}

	/**
	 * Get widget title.
	 *
	 * @since 1.0.0
	 *
	 * @return string
	 */
	public function get_title(): string {

		return esc_html__( 'Booking Form', 'sugar-calendar-bookings-scheduling-appointments-lite' );
	}

	/**
	 * Get widget icon.
	 *
	 * @since 1.0.0
	 *
	 * @return string
	 */
	public function get_icon(): string {

		return 'scbookings-elementor-icon';
	}

	/**
	 * Get widget categories.
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	public function get_categories(): array {

		return [ 'general' ];
	}

	/**
	 * Get widget keywords.
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	public function get_keywords(): array {

		return [ 'booking', 'bookings', 'form', 'calendar', 'appointment', 'appointments', 'scheduling', 'sugar calendar', 'scheduling appointments' ];
	}

	/**
	 * Get script dependencies.
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	public function get_script_depends(): array {

		return [ 'scbookings-booking-form-script' ];
	}

	/**
	 * Get style dependencies.
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	public function get_style_depends(): array {

		return [ 'scbookings-booking-form-style' ];
	}

	/**
	 * Register widget assets (scripts and styles).
	 *
	 * Note: Booking form frontend assets are registered globally via BookingFormAssets class.
	 *
	 * @since 1.0.0
	 */
	public function register_widget_assets(): void {

		// Register React JSX Runtime.
		$this->register_react_jsx_runtime();

		// Register Elementor-specific preview script.
		$this->register_elementor_preview_script();
	}

	/**
	 * Enqueue preview assets for Elementor editor.
	 *
	 * @since 1.0.0
	 */
	public function enqueue_preview_assets(): void {

		wp_enqueue_script( 'scbookings-elementor-booking-form-script' );
		wp_enqueue_script( 'react-jsx-runtime' );

		wp_localize_script(
			'scbookings-elementor-booking-form-script',
			'sugar_calendar_bookings',
			Plugin::get( BookingFormService::class )->get_script_data()
		);
	}

	/**
	 * Register widget controls.
	 *
	 * @since 1.0.0
	 */
	protected function register_controls(): void {

		// Content Tab Controls.
		$this->register_content_controls();

		// Style Tab Controls.
		$this->register_style_controls();
	}

	/**
	 * Register content tab controls.
	 *
	 * @since 1.0.0
	 */
	private function register_content_controls(): void {

		// Services Section.
		$this->start_controls_section(
			'services_section',
			[
				'label' => esc_html__( 'Services', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'tab'   => Controls_Manager::TAB_CONTENT,
			]
		);

		$services_options = $this->get_services_options();

		$this->add_control(
			'services',
			[
				'label'       => esc_html__( 'Select Services', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'type'        => Controls_Manager::SELECT2,
				'multiple'    => true,
				'options'     => $services_options,
				'default'     => [],
				'description' => esc_html__( 'Choose which services to display in the booking form. Leave empty to show all services.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			]
		);

		$this->end_controls_section();

		// Display Settings Section.
		$this->start_controls_section(
			'display_section',
			[
				'label' => esc_html__( 'Display Settings', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'tab'   => Controls_Manager::TAB_CONTENT,
			]
		);

		$this->add_control(
			'show_service_image',
			[
				'label'        => esc_html__( 'Show Service Image', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Show', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'label_off'    => esc_html__( 'Hide', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'return_value' => 'yes',
				'default'      => 'yes',
				'description'  => esc_html__( 'Show or hide the service feature image.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			]
		);

		$this->add_control(
			'show_service_description',
			[
				'label'        => esc_html__( 'Show Service Description', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Show', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'label_off'    => esc_html__( 'Hide', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'return_value' => 'yes',
				'default'      => 'yes',
				'description'  => esc_html__( 'Show or hide the service description.', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
			]
		);

		$this->end_controls_section();
	}

	/**
	 * Register style tab controls.
	 *
	 * @since 1.0.0
	 */
	private function register_style_controls(): void {

		// Layout Section.
		$this->start_controls_section(
			'layout_section',
			[
				'label' => esc_html__( 'Layout', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_control(
			'time_slot_layout',
			[
				'label'   => esc_html__( 'Time Slot Layout', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'type'    => Controls_Manager::SELECT,
				'options' => [
					'2-column' => esc_html__( '2 Column', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
					'3-column' => esc_html__( '3 Column', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				],
				'default' => '2-column',
			]
		);

		$this->end_controls_section();

		// Appearance Section.
		$this->start_controls_section(
			'appearance_section',
			[
				'label' => esc_html__( 'Appearance', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_control(
			'form_appearance',
			[
				'label'   => esc_html__( 'Form Theme', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'type'    => Controls_Manager::SELECT,
				'options' => [
					'light' => esc_html__( 'Light', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
					'dark'  => esc_html__( 'Dark', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
					'auto'  => esc_html__( 'Auto', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				],
				'default' => 'light',
			]
		);

		$this->add_control(
			'hide_branding',
			[
				'label'        => esc_html__( 'Hide Sugar Calendar Branding', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Hide', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'label_off'    => esc_html__( 'Show', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				'return_value' => 'yes',
				'default'      => '',
				'separator'    => 'before',
			]
		);

		$this->end_controls_section();
	}

	/**
	 * Render widget output.
	 *
	 * @since 1.0.0
	 * @since 1.5.0 Enqueue antispam captcha script when a provider is configured.
	 */
	protected function render(): void {

		$assets = Plugin::get( Assets::class );

		if ( $assets->is_dev() ) {
			$assets->enqueue_dev_runtime();
		}

		$settings = $this->get_settings_for_display();

		// Convert Elementor settings to block-compatible attributes.
		$attributes = $this->normalize_elementor_settings( $settings );

		// Get booking form data using the same service as the block.
		$booking_form_data = Plugin::get( BookingFormService::class )->get_booking_form_data( $attributes['services'] );

		// Add the booking form data to attributes for the markup.
		$attributes['initialData'] = $booking_form_data;

		// Render the widget markup.
		$this->render_booking_container( $attributes );

		// Enqueue antispam captcha script if a provider is configured.
		Plugin::get( BookingFormAssets::class )->enqueue_antispam_third_party_script();
	}

	/**
	 * Get available services for the select control.
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	private function get_services_options(): array {

		try {
			$services = Plugin::get( BookingFormService::class )->get_services_list_data();

			$options = [];

			foreach ( $services as $service ) {
				$options[ $service['id'] ] = $service['name'];
			}

			return $options;
		} catch ( \Exception $e ) {
			return [];
		}
	}

	/**
	 * Normalize Elementor settings to match block format.
	 *
	 * @since 1.0.0
	 *
	 * @param array $settings Elementor widget settings.
	 *
	 * @return array Normalized attributes matching block.json structure.
	 */
	private function normalize_elementor_settings( array $settings ): array {

		$services = ! empty( $settings['services'] ) && is_array( $settings['services'] )
			? array_map( 'intval', $settings['services'] )
			: [];

		$show_service_image       = ! empty( $settings['show_service_image'] ) && $settings['show_service_image'] === 'yes';
		$show_service_description = ! empty( $settings['show_service_description'] ) && $settings['show_service_description'] === 'yes';
		$hide_branding            = ! empty( $settings['hide_branding'] ) && $settings['hide_branding'] === 'yes';

		$time_slot_layout = in_array( $settings['time_slot_layout'] ?? '', [ '2-column', '3-column' ], true )
			? $settings['time_slot_layout']
			: '2-column';

		$form_appearance = in_array( $settings['form_appearance'] ?? '', [ 'light', 'dark', 'auto' ], true )
			? $settings['form_appearance']
			: 'light';

		return [
			'services'               => $services,
			'showServiceImage'       => $show_service_image,
			'showServiceDescription' => $show_service_description,
			'timeSlotLayout'         => $time_slot_layout,
			'formAppearance'         => $form_appearance,
			'hideBranding'           => $hide_branding,
		];
	}

	/**
	 * Register React JSX Runtime if not available.
	 *
	 * @since 1.0.0
	 */
	private function register_react_jsx_runtime(): void {

		if ( ! wp_script_is( 'react-jsx-runtime', 'registered' ) ) {
			wp_register_script(
				'react-jsx-runtime',
				SCBOOKINGS_PLUGIN_URL . 'assets/lib/react-jsx-runtime.js',
				[ 'react' ],
				'18.3.1',
				true
			);
		}
	}

	/**
	 * Register Elementor-specific preview script.
	 *
	 * Note: Booking form frontend assets are registered globally via BookingFormAssets class.
	 *
	 * @since 1.0.0
	 */
	private function register_elementor_preview_script(): void {

		wp_register_script(
			'scbookings-elementor-booking-form-script',
			SCBOOKINGS_PLUGIN_URL . 'assets/dist/admin/elementor/preview.js',
			[ 'wp-element', 'react-jsx-runtime', 'elementor-frontend', 'jquery' ],
			SCBOOKINGS_PLUGIN_VERSION,
			true
		);
	}

	/**
	 * Render the widget markup.
	 *
	 * @since 1.0.0
	 *
	 * @param array $attributes Normalized widget attributes.
	 */
	private function render_booking_container( array $attributes ): void {

		$wrapper_id = 'scbookings-elementor-' . uniqid();

		$wrapper_classes = [
			'scbookings-sc-bookings-form',
			'scbookings-elementor-wrapper',
		];

		if ( ! empty( $attributes['formAppearance'] ) ) {
			$wrapper_classes[] = 'scbookings-appearance-' . $attributes['formAppearance'];
		}

		if ( ! empty( $attributes['timeSlotLayout'] ) ) {
			$wrapper_classes[] = 'scbookings-layout-' . $attributes['timeSlotLayout'];
		}

		$wrapper_class   = implode( ' ', $wrapper_classes );
		$attributes_json = wp_json_encode( $attributes );
		$attributes_data = _wp_specialchars( $attributes_json, ENT_QUOTES, 'UTF-8', true );
		?>
		<div id="<?php echo esc_attr( $wrapper_id ); ?>" class="<?php echo esc_attr( $wrapper_class ); ?>">
			<div
				class="scbookings-sc-bookings-form-container"
				data-block-data="<?php echo $attributes_data; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>"
			>
			</div>
		</div>
		<?php
	}
}
