<?php
/**
 * DESCRIPTION: Elementor "Event Calendar" widget. Emits the same .nb-event-calendar mount markup as
 * DESCRIPTION: the Event_Calendar block; the live React calendar mounts on both frontend and editor.
 * DESCRIPTION: Style tab controls map to CSS custom properties for visual customization.
 *
 * @since   PBOOKING_SINCE
 * @package NemtlyBooking\Integrations\Elementor
 */

namespace NemtlyBooking\Integrations\Elementor;

use Elementor\Controls_Manager;
use NemtlyBooking\Core\Status;

/**
 * Event Calendar widget.
 *
 * @since PBOOKING_SINCE
 */
class Event_Calendar_Widget extends Abstract_Widget {

	/**
	 * Widget machine name.
	 *
	 * @since PBOOKING_SINCE
	 *
	 * @return string
	 */
	public function get_name() {
		return 'nemtly-event-calendar';
	}

	/**
	 * Widget title shown in the panel.
	 *
	 * @since PBOOKING_SINCE
	 *
	 * @return string
	 */
	public function get_title() {
		return __( 'Event Calendar', 'nemtly-booking' );
	}

	/**
	 * Panel icon.
	 *
	 * @since PBOOKING_SINCE
	 *
	 * @return string
	 */
	public function get_icon() {
		return 'eicon-calendar';
	}

	/**
	 * Search keywords.
	 *
	 * @since PBOOKING_SINCE
	 *
	 * @return string[]
	 */
	public function get_keywords() {
		return [ 'nemtly', 'booking', 'calendar', 'events', 'schedule', 'agenda' ];
	}

	/**
	 * Register the widget controls.
	 *
	 * @since PBOOKING_SINCE
	 *
	 * @return void
	 */
	protected function register_controls() {
		$this->register_content_controls();
		$this->register_style_controls();
	}

	/**
	 * Content tab — calendar behaviour and data settings.
	 *
	 * @since PBOOKING_SINCE
	 *
	 * @return void
	 */
	private function register_content_controls() {
		$this->start_controls_section(
			'section_content',
			[
				'label' => __( 'Calendar', 'nemtly-booking' ),
				'tab'   => Controls_Manager::TAB_CONTENT,
			]
		);

		$this->add_control(
			'default_view',
			[
				'label'   => __( 'Default view', 'nemtly-booking' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'month',
				'options' => [
					'month' => __( 'Month', 'nemtly-booking' ),
					'week'  => __( 'Week', 'nemtly-booking' ),
					'day'   => __( 'Day', 'nemtly-booking' ),
					'list'  => __( 'List', 'nemtly-booking' ),
				],
			]
		);

		$this->add_control(
			'available_views',
			[
				'label'       => __( 'Available views', 'nemtly-booking' ),
				'type'        => Controls_Manager::SELECT2,
				'multiple'    => true,
				'label_block' => true,
				'default'     => [ 'month', 'week', 'day', 'list' ],
				'options'     => [
					'month' => __( 'Month', 'nemtly-booking' ),
					'week'  => __( 'Week', 'nemtly-booking' ),
					'day'   => __( 'Day', 'nemtly-booking' ),
					'list'  => __( 'List', 'nemtly-booking' ),
				],
			]
		);

		$this->add_control(
			'show_toolbar',
			[
				'label'        => __( 'Show toolbar', 'nemtly-booking' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => __( 'Yes', 'nemtly-booking' ),
				'label_off'    => __( 'No', 'nemtly-booking' ),
				'return_value' => 'yes',
				'default'      => 'yes',
			]
		);

		$this->add_control(
			'show_filters',
			[
				'label'        => __( 'Show filters', 'nemtly-booking' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => __( 'Yes', 'nemtly-booking' ),
				'label_off'    => __( 'No', 'nemtly-booking' ),
				'return_value' => 'yes',
				'default'      => 'yes',
			]
		);

		$this->add_control(
			'categories',
			[
				'label'       => __( 'Filter by categories', 'nemtly-booking' ),
				'type'        => Controls_Manager::SELECT2,
				'multiple'    => true,
				'label_block' => true,
				'options'     => $this->get_term_options( 'nemtly_event_category' ),
				'description' => __( 'Leave empty to show all categories.', 'nemtly-booking' ),
			]
		);

		$this->add_control(
			'tags',
			[
				'label'       => __( 'Filter by tags', 'nemtly-booking' ),
				'type'        => Controls_Manager::SELECT2,
				'multiple'    => true,
				'label_block' => true,
				'options'     => $this->get_term_options( 'nemtly_event_tag' ),
				'description' => __( 'Leave empty to show all tags.', 'nemtly-booking' ),
			]
		);

		$this->add_control(
			'event_type',
			[
				'label'   => __( 'Event type', 'nemtly-booking' ),
				'type'    => Controls_Manager::SELECT,
				'default' => '',
				'options' => [
					''                            => __( 'All', 'nemtly-booking' ),
					Status::EVENT_TYPE_ONE_ON_ONE => __( 'One-on-one', 'nemtly-booking' ),
					Status::EVENT_TYPE_GROUP      => __( 'Group', 'nemtly-booking' ),
					Status::EVENT_TYPE_EVENT      => __( 'Event', 'nemtly-booking' ),
				],
			]
		);

		$this->add_control(
			'first_day_of_week',
			[
				'label'   => __( 'First day of week', 'nemtly-booking' ),
				'type'    => Controls_Manager::SELECT,
				'default' => '0',
				'options' => [
					'0' => __( 'Sunday', 'nemtly-booking' ),
					'1' => __( 'Monday', 'nemtly-booking' ),
					'2' => __( 'Tuesday', 'nemtly-booking' ),
					'3' => __( 'Wednesday', 'nemtly-booking' ),
					'4' => __( 'Thursday', 'nemtly-booking' ),
					'5' => __( 'Friday', 'nemtly-booking' ),
					'6' => __( 'Saturday', 'nemtly-booking' ),
				],
			]
		);

		$this->add_control(
			'events_per_cell',
			[
				'label'   => __( 'Events per day cell', 'nemtly-booking' ),
				'type'    => Controls_Manager::NUMBER,
				'default' => 3,
				'min'     => 1,
				'max'     => 10,
			]
		);

		$this->add_control(
			'show_booking_btn',
			[
				'label'        => __( 'Show booking button', 'nemtly-booking' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => __( 'Yes', 'nemtly-booking' ),
				'label_off'    => __( 'No', 'nemtly-booking' ),
				'return_value' => 'yes',
				'default'      => 'yes',
			]
		);

		$this->add_control(
			'show_past_events',
			[
				'label'        => __( 'Show past events', 'nemtly-booking' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => __( 'Yes', 'nemtly-booking' ),
				'label_off'    => __( 'No', 'nemtly-booking' ),
				'return_value' => 'yes',
				'default'      => '',
			]
		);

		$this->add_control(
			'calendar_height',
			[
				'label'   => __( 'Height', 'nemtly-booking' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'auto',
				'options' => [
					'auto'  => __( 'Auto', 'nemtly-booking' ),
					'fixed' => __( 'Fixed', 'nemtly-booking' ),
				],
			]
		);

		$this->add_control(
			'calendar_height_px',
			[
				'label'     => __( 'Fixed height (px)', 'nemtly-booking' ),
				'type'      => Controls_Manager::NUMBER,
				'default'   => 600,
				'min'       => 300,
				'max'       => 2000,
				'condition' => [
					'calendar_height' => 'fixed',
				],
			]
		);

		$this->end_controls_section();
	}

	/**
	 * Style tab — visual controls that map to CSS custom properties on the wrapper.
	 *
	 * @since PBOOKING_SINCE
	 *
	 * @return void
	 */
	private function register_style_controls() {
		$this->start_controls_section(
			'section_style_header',
			[
				'label' => __( 'Header', 'nemtly-booking' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_control(
			'style_header_bg',
			[
				'label'   => __( 'Background', 'nemtly-booking' ),
				'type'    => Controls_Manager::COLOR,
				'default' => '',
			]
		);

		$this->add_control(
			'style_header_text',
			[
				'label'   => __( 'Text Color', 'nemtly-booking' ),
				'type'    => Controls_Manager::COLOR,
				'default' => '',
			]
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'section_style_grid',
			[
				'label' => __( 'Calendar Grid', 'nemtly-booking' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_control(
			'style_cell_bg',
			[
				'label'   => __( 'Cell Background', 'nemtly-booking' ),
				'type'    => Controls_Manager::COLOR,
				'default' => '',
			]
		);

		$this->add_control(
			'style_cell_text',
			[
				'label'   => __( 'Cell Text Color', 'nemtly-booking' ),
				'type'    => Controls_Manager::COLOR,
				'default' => '',
			]
		);

		$this->add_responsive_control(
			'style_cell_radius',
			[
				'label'      => __( 'Cell Border Radius', 'nemtly-booking' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px' ],
				'range'      => [
					'px' => [
						'min'  => 0,
						'max'  => 24,
						'step' => 1,
					],
				],
				'default'    => [
					'unit' => 'px',
					'size' => '',
				],
			]
		);

		$this->add_control(
			'style_today_heading',
			[
				'label'     => __( 'Today Indicator', 'nemtly-booking' ),
				'type'      => Controls_Manager::HEADING,
				'separator' => 'before',
			]
		);

		$this->add_control(
			'style_today_bg',
			[
				'label'   => __( 'Today Cell Background', 'nemtly-booking' ),
				'type'    => Controls_Manager::COLOR,
				'default' => '',
			]
		);

		$this->add_control(
			'style_today_text',
			[
				'label'   => __( 'Today Cell Text', 'nemtly-booking' ),
				'type'    => Controls_Manager::COLOR,
				'default' => '',
			]
		);

		$this->add_control(
			'style_accent',
			[
				'label'       => __( 'Accent Color', 'nemtly-booking' ),
				'type'        => Controls_Manager::COLOR,
				'default'     => '',
				'description' => __( 'Used for active view button, today button, and interactive highlights.', 'nemtly-booking' ),
			]
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'section_style_events',
			[
				'label' => __( 'Event Badges', 'nemtly-booking' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_control(
			'style_event_bg',
			[
				'label'   => __( 'Badge Background', 'nemtly-booking' ),
				'type'    => Controls_Manager::COLOR,
				'default' => '',
			]
		);

		$this->add_control(
			'style_event_text',
			[
				'label'   => __( 'Badge Text Color', 'nemtly-booking' ),
				'type'    => Controls_Manager::COLOR,
				'default' => '',
			]
		);

		$this->add_responsive_control(
			'style_event_radius',
			[
				'label'      => __( 'Badge Border Radius', 'nemtly-booking' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => [ 'px' ],
				'range'      => [
					'px' => [
						'min'  => 0,
						'max'  => 16,
						'step' => 1,
					],
				],
				'default'    => [
					'unit' => 'px',
					'size' => '',
				],
			]
		);

		$this->end_controls_section();
	}

	/**
	 * Build an inline style string from the Style control values.
	 *
	 * @since PBOOKING_SINCE
	 *
	 * @param array $settings Widget settings array.
	 *
	 * @return string
	 */
	private function build_style_vars( array $settings ) {
		$map = [
			'style_header_bg'   => '--nb-cal-header-bg',
			'style_header_text' => '--nb-cal-header-text',
			'style_cell_bg'     => '--nb-cal-cell-bg',
			'style_cell_text'   => '--nb-cal-cell-text',
			'style_today_bg'    => '--nb-cal-today-bg',
			'style_today_text'  => '--nb-cal-today-text',
			'style_accent'      => '--nb-cal-accent',
			'style_event_bg'    => '--nb-cal-event-bg',
			'style_event_text'  => '--nb-cal-event-text',
		];

		$pairs = [];

		foreach ( $map as $setting_key => $css_var ) {
			$value = $settings[ $setting_key ] ?? '';
			if ( '' !== $value ) {
				$pairs[] = sprintf( '%s:%s', $css_var, esc_attr( $value ) );
			}
		}

		$radius_keys = [
			'style_cell_radius'  => '--nb-cal-cell-radius',
			'style_event_radius' => '--nb-cal-event-radius',
		];

		foreach ( $radius_keys as $setting_key => $css_var ) {
			$value = $settings[ $setting_key ]['size'] ?? '';
			if ( '' !== $value ) {
				$pairs[] = sprintf( '%s:%spx', $css_var, (float) $value );
			}
		}

		if ( empty( $pairs ) ) {
			return '';
		}

		return 'style="' . implode( ';', $pairs ) . '"';
	}

	/**
	 * Render the widget.
	 *
	 * @since PBOOKING_SINCE
	 *
	 * @return void
	 */
	protected function render() {
		$settings = $this->get_settings_for_display();

		$available_views = ! empty( $settings['available_views'] ) && is_array( $settings['available_views'] )
			? array_values( array_intersect( $settings['available_views'], [ 'month', 'week', 'day', 'list' ] ) )
			: [ 'month', 'week', 'day', 'list' ];

		$style_attr = $this->build_style_vars( $settings );

		if ( ! $this->is_editor_preview() ) {
			$this->enqueue_calendar_assets(
				[
					'defaultView'      => ! empty( $settings['default_view'] ) ? $settings['default_view'] : 'month',
					'availableViews'   => $available_views,
					'firstDayOfWeek'   => isset( $settings['first_day_of_week'] ) ? (int) $settings['first_day_of_week'] : 0,
					'eventsPerCell'    => isset( $settings['events_per_cell'] ) ? (int) $settings['events_per_cell'] : 3,
					'showBookingBtn'   => ! empty( $settings['show_booking_btn'] ),
					'showPastEvents'   => ! empty( $settings['show_past_events'] ),
					'calendarHeight'   => ! empty( $settings['calendar_height'] ) ? $settings['calendar_height'] : 'auto',
					'calendarHeightPx' => isset( $settings['calendar_height_px'] ) ? (int) $settings['calendar_height_px'] : 600,
				]
			);
		}

		$categories = ! empty( $settings['categories'] ) && is_array( $settings['categories'] )
			? implode( ',', array_map( 'absint', $settings['categories'] ) )
			: '';
		$tags       = ! empty( $settings['tags'] ) && is_array( $settings['tags'] )
			? implode( ',', array_map( 'absint', $settings['tags'] ) )
			: '';

		$events_per_cell = isset( $settings['events_per_cell'] ) ? (int) $settings['events_per_cell'] : 3;

		$week_starts_on = isset( $settings['first_day_of_week'] ) ? (int) $settings['first_day_of_week'] : 0;

		printf(
			'<div class="nb-event-calendar" %1$s data-view="%2$s" data-views="%3$s" data-categories="%4$s" data-tags="%5$s" data-event-type="%6$s" data-show-toolbar="%7$s" data-show-filters="%8$s" data-week-starts-on="%9$s" data-events-per-cell="%10$s"><noscript><p>%11$s</p></noscript></div>',
			$style_attr, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			esc_attr( ! empty( $settings['default_view'] ) ? $settings['default_view'] : '' ),
			esc_attr( implode( ',', $available_views ) ),
			esc_attr( $categories ),
			esc_attr( $tags ),
			esc_attr( ! empty( $settings['event_type'] ) ? $settings['event_type'] : '' ),
			! empty( $settings['show_toolbar'] ) ? 'true' : 'false',
			! empty( $settings['show_filters'] ) ? 'true' : 'false',
			esc_attr( $week_starts_on ),
			esc_attr( $events_per_cell ),
			esc_html__( 'Please enable JavaScript to view the event calendar.', 'nemtly-booking' )
		);
	}
}
