<?php
/**
 * Widget Name: Countdown
 * Description: A professional evergreen / due-date countdown timer with selectable
 *              visual styles, toggleable day / hour / minute / second units, custom
 *              labels, separators and configurable expiry behaviour ( message, hide
 *              or redirect ). Only the selected style CSS file is loaded on the
 *              frontend and the target time is computed in the site timezone.
 *
 * @package    captain-widgets-kit
 * @subpackage captain-widgets-kit/includes
 * @since      1.3.0
 */

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

use Elementor\Widget_Base;
use Elementor\Controls_Manager;
use Elementor\Group_Control_Typography;
use Elementor\Group_Control_Box_Shadow;
use Elementor\Group_Control_Border;
use Elementor\Group_Control_Background;

/**
 * Class Captwiki_Countdown
 *
 * @since 1.3.0
 */
class Captwiki_Countdown extends Widget_Base {

	/**
	 * Get widget name.
	 *
	 * @since 1.3.0
	 * @return string
	 */
	public function get_name(): string {
		return 'captwiki-countdown';
	}

	/**
	 * Get widget title.
	 *
	 * @since 1.3.0
	 * @return string
	 */
	public function get_title(): string {
		return esc_html__( 'Countdown', 'captain-widgets-kit' );
	}

	/**
	 * Get widget icon.
	 *
	 * @since 1.3.0
	 * @return string
	 */
	public function get_icon(): string {
		return 'eicon-countdown captwiki-el-logo';
	}

	/**
	 * Get widget categories.
	 *
	 * @since 1.3.0
	 * @return array
	 */
	public function get_categories(): array {
		return array( 'captwiki-essential' );
	}

	/**
	 * Get widget keywords.
	 *
	 * @since 1.3.0
	 * @return array
	 */
	public function get_keywords(): array {
		return array( 'countdown', 'timer', 'clock', 'evergreen', 'deadline', 'sale', 'captain-widgets-kit' );
	}

	/**
	 * Common stylesheet dependency.
	 *
	 * @since 1.3.0
	 * @return array
	 */
	public function get_style_depends(): array {
		return array( 'captwiki_countdown' );
	}

	/**
	 * Frontend script dependency.
	 *
	 * @since 1.3.0
	 * @return array
	 */
	public function get_script_depends(): array {
		return array( 'captwiki-countdown' );
	}

	/**
	 * Disable Elementor's default inner wrapper.
	 *
	 * @since 1.3.0
	 * @return bool
	 */
	public function has_widget_inner_wrapper(): bool {
		return ! \Elementor\Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' );
	}

	/**
	 * Selectable visual styles.
	 *
	 * @since 1.3.0
	 * @return array
	 */
	private function captwiki_style_options(): array {
		return array(
			'style-1' => esc_html__( 'Style 1 – Classic Boxes', 'captain-widgets-kit' ),
			'style-2' => esc_html__( 'Style 2 – Solid Filled', 'captain-widgets-kit' ),
			'style-3' => esc_html__( 'Style 3 – Minimal Inline', 'captain-widgets-kit' ),
			'style-4' => esc_html__( 'Style 4 – Outline Cards', 'captain-widgets-kit' ),
			'style-5' => esc_html__( 'Style 5 – Circular', 'captain-widgets-kit' ),
		);
	}

	/**
	 * Countdown unit definitions.
	 *
	 * @since 1.3.0
	 * @return array
	 */
	private function captwiki_units(): array {
		return array(
			'days'    => esc_html__( 'Days', 'captain-widgets-kit' ),
			'hours'   => esc_html__( 'Hours', 'captain-widgets-kit' ),
			'minutes' => esc_html__( 'Minutes', 'captain-widgets-kit' ),
			'seconds' => esc_html__( 'Seconds', 'captain-widgets-kit' ),
		);
	}

	/**
	 * Register widget controls.
	 *
	 * @since 1.3.0
	 * @return void
	 */
	protected function register_controls(): void {
		$this->register_content_controls();
		$this->register_units_controls();
		$this->register_expiry_controls();
		$this->register_general_style_controls();
		$this->register_box_style_controls();
		$this->register_digit_style_controls();
		$this->register_label_style_controls();
		$this->register_separator_style_controls();
		$this->register_message_style_controls();
	}

	/**
	 * Content tab — main controls.
	 *
	 * @since 1.3.0
	 * @return void
	 */
	private function register_content_controls(): void {

		$this->start_controls_section(
			'section_countdown_content',
			array(
				'label' => esc_html__( 'Countdown', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_CONTENT,
			)
		);

		$this->add_control(
			'widget_style',
			array(
				'label'   => esc_html__( 'Style', 'captain-widgets-kit' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'style-1',
				'options' => $this->captwiki_style_options(),
			)
		);

		$this->add_control(
			'countdown_type',
			array(
				'label'   => esc_html__( 'Type', 'captain-widgets-kit' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'due_date',
				'options' => array(
					'due_date'  => esc_html__( 'Due Date ( fixed )', 'captain-widgets-kit' ),
					'evergreen' => esc_html__( 'Evergreen ( per visitor )', 'captain-widgets-kit' ),
				),
			)
		);

		$this->add_control(
			'due_date',
			array(
				'label'       => esc_html__( 'Due Date', 'captain-widgets-kit' ),
				'type'        => Controls_Manager::DATE_TIME,
				'default'     => gmdate( 'Y-m-d H:i', strtotime( '+7 days' ) ),
				'description' => esc_html__( 'Target date & time, evaluated in your site timezone.', 'captain-widgets-kit' ),
				'condition'   => array( 'countdown_type' => 'due_date' ),
			)
		);

		$this->add_control(
			'evergreen_days',
			array(
				'label'     => esc_html__( 'Days', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::NUMBER,
				'min'       => 0,
				'default'   => 0,
				'condition' => array( 'countdown_type' => 'evergreen' ),
			)
		);

		$this->add_control(
			'evergreen_hours',
			array(
				'label'     => esc_html__( 'Hours', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::NUMBER,
				'min'       => 0,
				'max'       => 23,
				'default'   => 1,
				'condition' => array( 'countdown_type' => 'evergreen' ),
			)
		);

		$this->add_control(
			'evergreen_minutes',
			array(
				'label'     => esc_html__( 'Minutes', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::NUMBER,
				'min'       => 0,
				'max'       => 59,
				'default'   => 30,
				'condition' => array( 'countdown_type' => 'evergreen' ),
			)
		);

		$this->add_control(
			'evergreen_note',
			array(
				'type'            => Controls_Manager::RAW_HTML,
				'raw'             => esc_html__( 'Evergreen timers restart for each visitor and persist in their browser until they expire.', 'captain-widgets-kit' ),
				'content_classes' => 'elementor-descriptor',
				'condition'       => array( 'countdown_type' => 'evergreen' ),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Content tab — unit controls.
	 *
	 * @since 1.3.0
	 * @return void
	 */
	private function register_units_controls(): void {

		$this->start_controls_section(
			'section_units_content',
			array(
				'label' => esc_html__( 'Units', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_CONTENT,
			)
		);

		foreach ( $this->captwiki_units() as $unit => $label ) {
			$this->add_control(
				'show_' . $unit,
				array(
					/* translators: %s: unit name ( Days, Hours… ). */
					'label'        => sprintf( esc_html__( 'Show %s', 'captain-widgets-kit' ), $label ),
					'type'         => Controls_Manager::SWITCHER,
					'label_on'     => esc_html__( 'Show', 'captain-widgets-kit' ),
					'label_off'    => esc_html__( 'Hide', 'captain-widgets-kit' ),
					'return_value' => 'yes',
					'default'      => 'yes',
				)
			);

			$this->add_control(
				'label_' . $unit,
				array(
					'label'       => esc_html__( 'Label', 'captain-widgets-kit' ),
					'type'        => Controls_Manager::TEXT,
					'default'     => $label,
					'label_block' => true,
					'condition'   => array(
						'show_' . $unit => 'yes',
						'show_labels'   => 'yes',
					),
				)
			);
		}

		$this->add_control(
			'show_labels',
			array(
				'label'        => esc_html__( 'Show Labels', 'captain-widgets-kit' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Show', 'captain-widgets-kit' ),
				'label_off'    => esc_html__( 'Hide', 'captain-widgets-kit' ),
				'return_value' => 'yes',
				'default'      => 'yes',
				'separator'    => 'before',
			)
		);

		$this->add_control(
			'show_separator',
			array(
				'label'        => esc_html__( 'Show Separator', 'captain-widgets-kit' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Show', 'captain-widgets-kit' ),
				'label_off'    => esc_html__( 'Hide', 'captain-widgets-kit' ),
				'return_value' => 'yes',
				'default'      => '',
			)
		);

		$this->add_control(
			'separator_char',
			array(
				'label'     => esc_html__( 'Separator', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::TEXT,
				'default'   => ':',
				'condition' => array( 'show_separator' => 'yes' ),
			)
		);

		$this->add_control(
			'pad_zero',
			array(
				'label'        => esc_html__( 'Leading Zero', 'captain-widgets-kit' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'On', 'captain-widgets-kit' ),
				'label_off'    => esc_html__( 'Off', 'captain-widgets-kit' ),
				'return_value' => 'yes',
				'default'      => 'yes',
				'description'  => esc_html__( 'Show 2-digit numbers ( 05 instead of 5 ).', 'captain-widgets-kit' ),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Content tab — expiry controls.
	 *
	 * @since 1.3.0
	 * @return void
	 */
	private function register_expiry_controls(): void {

		$this->start_controls_section(
			'section_expiry_content',
			array(
				'label' => esc_html__( 'After Expire', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_CONTENT,
			)
		);

		$this->add_control(
			'expire_action',
			array(
				'label'   => esc_html__( 'Action', 'captain-widgets-kit' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'message',
				'options' => array(
					'none'     => esc_html__( 'Do Nothing ( keep zeros )', 'captain-widgets-kit' ),
					'message'  => esc_html__( 'Show Message', 'captain-widgets-kit' ),
					'hide'     => esc_html__( 'Hide Timer', 'captain-widgets-kit' ),
					'redirect' => esc_html__( 'Redirect', 'captain-widgets-kit' ),
				),
			)
		);

		$this->add_control(
			'expire_message',
			array(
				'label'     => esc_html__( 'Message', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::TEXTAREA,
				'rows'      => 3,
				'default'   => esc_html__( 'This offer has ended.', 'captain-widgets-kit' ),
				'dynamic'   => array( 'active' => true ),
				'condition' => array( 'expire_action' => 'message' ),
			)
		);

		$this->add_control(
			'redirect_url',
			array(
				'label'         => esc_html__( 'Redirect URL', 'captain-widgets-kit' ),
				'type'          => Controls_Manager::URL,
				'placeholder'   => esc_html__( 'https://your-link.com', 'captain-widgets-kit' ),
				'show_external' => false,
				'options'       => false,
				'condition'     => array( 'expire_action' => 'redirect' ),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * General (wrapper) style controls.
	 *
	 * @since 1.3.0
	 * @return void
	 */
	private function register_general_style_controls(): void {

		$this->start_controls_section(
			'section_general_style',
			array(
				'label' => esc_html__( 'General', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			)
		);

		$this->add_responsive_control(
			'alignment',
			array(
				'label'     => esc_html__( 'Alignment', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::CHOOSE,
				'default'   => 'center',
				'options'   => array(
					'flex-start' => array(
						'title' => esc_html__( 'Left', 'captain-widgets-kit' ),
						'icon'  => 'eicon-align-start-h',
					),
					'center'     => array(
						'title' => esc_html__( 'Center', 'captain-widgets-kit' ),
						'icon'  => 'eicon-align-center-h',
					),
					'flex-end'   => array(
						'title' => esc_html__( 'Right', 'captain-widgets-kit' ),
						'icon'  => 'eicon-align-end-h',
					),
				),
				'selectors' => array(
					'{{WRAPPER}} .captwiki-countdown__timer' => 'justify-content: {{VALUE}};',
				),
			)
		);

		$this->add_responsive_control(
			'item_gap',
			array(
				'label'      => esc_html__( 'Gap', 'captain-widgets-kit' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => array( 'px', 'em' ),
				'range'      => array( 'px' => array( 'min' => 0, 'max' => 80 ) ),
				'selectors'  => array(
					'{{WRAPPER}} .captwiki-countdown__timer' => 'gap: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'accent_color',
			array(
				'label'     => esc_html__( 'Accent Color', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => array(
					'{{WRAPPER}} .captwiki-countdown' => '--captwiki-cd-accent: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			Group_Control_Background::get_type(),
			array(
				'name'     => 'wrapper_background',
				'label'    => esc_html__( 'Background', 'captain-widgets-kit' ),
				'types'    => array( 'classic', 'gradient' ),
				'selector' => '{{WRAPPER}} .captwiki-countdown',
			)
		);

		$this->add_responsive_control(
			'wrapper_padding',
			array(
				'label'      => esc_html__( 'Padding', 'captain-widgets-kit' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%', 'em', 'rem' ),
				'selectors'  => array(
					'{{WRAPPER}} .captwiki-countdown' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'wrapper_margin',
			array(
				'label'      => esc_html__( 'Margin', 'captain-widgets-kit' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%', 'em', 'rem' ),
				'selectors'  => array(
					'{{WRAPPER}} .captwiki-countdown' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Box (unit) style controls.
	 *
	 * @since 1.3.0
	 * @return void
	 */
	private function register_box_style_controls(): void {

		$this->start_controls_section(
			'section_box_style',
			array(
				'label' => esc_html__( 'Box', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			)
		);

		$this->add_group_control(
			Group_Control_Background::get_type(),
			array(
				'name'     => 'box_background',
				'label'    => esc_html__( 'Background', 'captain-widgets-kit' ),
				'types'    => array( 'classic', 'gradient' ),
				'selector' => '{{WRAPPER}} .captwiki-countdown__item',
			)
		);

		$this->add_group_control(
			Group_Control_Border::get_type(),
			array(
				'name'     => 'box_border',
				'label'    => esc_html__( 'Border', 'captain-widgets-kit' ),
				'selector' => '{{WRAPPER}} .captwiki-countdown__item',
			)
		);

		$this->add_responsive_control(
			'box_radius',
			array(
				'label'      => esc_html__( 'Border Radius', 'captain-widgets-kit' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .captwiki-countdown__item' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_group_control(
			Group_Control_Box_Shadow::get_type(),
			array(
				'name'     => 'box_shadow',
				'label'    => esc_html__( 'Box Shadow', 'captain-widgets-kit' ),
				'selector' => '{{WRAPPER}} .captwiki-countdown__item',
			)
		);

		$this->add_responsive_control(
			'box_min_width',
			array(
				'label'      => esc_html__( 'Min Width', 'captain-widgets-kit' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => array( 'px', 'em' ),
				'range'      => array( 'px' => array( 'min' => 40, 'max' => 220 ) ),
				'selectors'  => array(
					'{{WRAPPER}} .captwiki-countdown__item' => 'min-width: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'box_padding',
			array(
				'label'      => esc_html__( 'Padding', 'captain-widgets-kit' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', 'em' ),
				'selectors'  => array(
					'{{WRAPPER}} .captwiki-countdown__item' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Digit style controls.
	 *
	 * @since 1.3.0
	 * @return void
	 */
	private function register_digit_style_controls(): void {

		$this->start_controls_section(
			'section_digit_style',
			array(
				'label' => esc_html__( 'Digits', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			)
		);

		$this->add_control(
			'digit_color',
			array(
				'label'     => esc_html__( 'Color', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => array(
					'{{WRAPPER}} .captwiki-countdown__digits' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			array(
				'name'     => 'digit_typography',
				'selector' => '{{WRAPPER}} .captwiki-countdown__digits',
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Label style controls.
	 *
	 * @since 1.3.0
	 * @return void
	 */
	private function register_label_style_controls(): void {

		$this->start_controls_section(
			'section_label_style',
			array(
				'label'     => esc_html__( 'Labels', 'captain-widgets-kit' ),
				'tab'       => Controls_Manager::TAB_STYLE,
				'condition' => array( 'show_labels' => 'yes' ),
			)
		);

		$this->add_control(
			'label_color',
			array(
				'label'     => esc_html__( 'Color', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => array(
					'{{WRAPPER}} .captwiki-countdown__label' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			array(
				'name'     => 'label_typography',
				'selector' => '{{WRAPPER}} .captwiki-countdown__label',
			)
		);

		$this->add_responsive_control(
			'label_spacing',
			array(
				'label'      => esc_html__( 'Spacing', 'captain-widgets-kit' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => array( 'px', 'em' ),
				'range'      => array( 'px' => array( 'min' => 0, 'max' => 40 ) ),
				'selectors'  => array(
					'{{WRAPPER}} .captwiki-countdown__label' => 'margin-top: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Separator style controls.
	 *
	 * @since 1.3.0
	 * @return void
	 */
	private function register_separator_style_controls(): void {

		$this->start_controls_section(
			'section_separator_style',
			array(
				'label'     => esc_html__( 'Separator', 'captain-widgets-kit' ),
				'tab'       => Controls_Manager::TAB_STYLE,
				'condition' => array( 'show_separator' => 'yes' ),
			)
		);

		$this->add_control(
			'separator_color',
			array(
				'label'     => esc_html__( 'Color', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => array(
					'{{WRAPPER}} .captwiki-countdown__sep' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			array(
				'name'     => 'separator_typography',
				'selector' => '{{WRAPPER}} .captwiki-countdown__sep',
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Expiry message style controls.
	 *
	 * @since 1.3.0
	 * @return void
	 */
	private function register_message_style_controls(): void {

		$this->start_controls_section(
			'section_message_style',
			array(
				'label'     => esc_html__( 'Expire Message', 'captain-widgets-kit' ),
				'tab'       => Controls_Manager::TAB_STYLE,
				'condition' => array( 'expire_action' => 'message' ),
			)
		);

		$this->add_control(
			'message_color',
			array(
				'label'     => esc_html__( 'Color', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => array(
					'{{WRAPPER}} .captwiki-countdown__message' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			array(
				'name'     => 'message_typography',
				'selector' => '{{WRAPPER}} .captwiki-countdown__message',
			)
		);

		$this->add_responsive_control(
			'message_align',
			array(
				'label'     => esc_html__( 'Alignment', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::CHOOSE,
				'options'   => array(
					'left'   => array(
						'title' => esc_html__( 'Left', 'captain-widgets-kit' ),
						'icon'  => 'eicon-text-align-left',
					),
					'center' => array(
						'title' => esc_html__( 'Center', 'captain-widgets-kit' ),
						'icon'  => 'eicon-text-align-center',
					),
					'right'  => array(
						'title' => esc_html__( 'Right', 'captain-widgets-kit' ),
						'icon'  => 'eicon-text-align-right',
					),
				),
				'selectors' => array(
					'{{WRAPPER}} .captwiki-countdown__message' => 'text-align: {{VALUE}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Resolve the target timestamp ( ms, UTC ) for the countdown.
	 *
	 * Due-date timers are computed once in the site timezone. Evergreen timers
	 * just emit a duration; the JS seeds & persists the per-visitor deadline.
	 *
	 * @since 1.3.0
	 * @param array $settings Widget settings.
	 * @return array { string $type, int $target_ms, int $duration_ms }
	 */
	private function captwiki_get_time_data( array $settings ): array {
		$type = 'evergreen' === $settings['countdown_type'] ? 'evergreen' : 'due_date';

		if ( 'evergreen' === $type ) {
			$days    = isset( $settings['evergreen_days'] ) ? max( 0, absint( $settings['evergreen_days'] ) ) : 0;
			$hours   = isset( $settings['evergreen_hours'] ) ? max( 0, absint( $settings['evergreen_hours'] ) ) : 0;
			$minutes = isset( $settings['evergreen_minutes'] ) ? max( 0, absint( $settings['evergreen_minutes'] ) ) : 0;

			$duration = ( ( $days * 86400 ) + ( $hours * 3600 ) + ( $minutes * 60 ) ) * 1000;

			return array(
				'type'        => 'evergreen',
				'target_ms'   => 0,
				'duration_ms' => $duration,
			);
		}

		$raw       = ! empty( $settings['due_date'] ) ? $settings['due_date'] : '';
		$target_ms = 0;

		if ( '' !== $raw ) {
			$date = date_create( $raw, wp_timezone() );
			if ( $date instanceof DateTime ) {
				$target_ms = $date->getTimestamp() * 1000;
			}
		}

		return array(
			'type'        => 'due_date',
			'target_ms'   => $target_ms,
			'duration_ms' => 0,
		);
	}

	/**
	 * Render a single unit box.
	 *
	 * @since 1.3.0
	 * @param string $unit     Unit key.
	 * @param array  $settings Widget settings.
	 * @return void
	 */
	private function captwiki_render_unit( string $unit, array $settings ): void {
		$show_labels = 'yes' === $settings['show_labels'];
		$label       = isset( $settings[ 'label_' . $unit ] ) ? $settings[ 'label_' . $unit ] : '';

		echo '<div class="captwiki-countdown__item captwiki-countdown__item--' . esc_attr( $unit ) . '" data-unit="' . esc_attr( $unit ) . '">';
			echo '<span class="captwiki-countdown__digits" data-value>00</span>';

		if ( $show_labels && '' !== trim( (string) $label ) ) {
			echo '<span class="captwiki-countdown__label">' . esc_html( $label ) . '</span>';
		}

		echo '</div>';
	}

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

		$allowed_styles = array_keys( $this->captwiki_style_options() );
		$style          = in_array( $settings['widget_style'], $allowed_styles, true ) ? $settings['widget_style'] : 'style-1';

		// Load only the active style stylesheet, depending on the common one.
		wp_enqueue_style(
			'captwiki-countdown-' . $style,
			CAPTWIKI_URL . 'assets/css/widgets/countdown/captwiki-countdown-' . $style . '.css',
			array( 'captwiki_countdown' ),
			CAPTWIKI_VERSION
		);

		$time          = $this->captwiki_get_time_data( $settings );
		$show_sep      = 'yes' === $settings['show_separator'];
		$sep_char      = $show_sep ? $settings['separator_char'] : '';
		$pad_zero      = 'yes' === $settings['pad_zero'] ? '1' : '0';
		$expire_action = in_array( $settings['expire_action'], array( 'none', 'message', 'hide', 'redirect' ), true ) ? $settings['expire_action'] : 'none';

		$redirect_url = '';
		if ( 'redirect' === $expire_action && ! empty( $settings['redirect_url']['url'] ) ) {
			$redirect_url = $settings['redirect_url']['url'];
		}

		// Stable per-widget id used to namespace evergreen browser storage.
		$instance_id = 'captwiki-cd-' . $this->get_id();

		$active_units = array();
		foreach ( $this->captwiki_units() as $unit => $label ) {
			if ( 'yes' === $settings[ 'show_' . $unit ] ) {
				$active_units[] = $unit;
			}
		}

		// Fallback so the timer is never empty.
		if ( empty( $active_units ) ) {
			$active_units = array( 'days', 'hours', 'minutes', 'seconds' );
		}

		$data_attr  = ' data-type="' . esc_attr( $time['type'] ) . '"';
		$data_attr .= ' data-target="' . esc_attr( $time['target_ms'] ) . '"';
		$data_attr .= ' data-duration="' . esc_attr( $time['duration_ms'] ) . '"';
		$data_attr .= ' data-pad="' . esc_attr( $pad_zero ) . '"';
		$data_attr .= ' data-expire="' . esc_attr( $expire_action ) . '"';
		$data_attr .= ' data-instance="' . esc_attr( $instance_id ) . '"';
		$data_attr .= ' data-units="' . esc_attr( implode( ',', $active_units ) ) . '"';

		if ( '' !== $redirect_url ) {
			$data_attr .= ' data-redirect="' . esc_url( $redirect_url ) . '"';
		}

		echo '<div class="captwiki-countdown captwiki-' . esc_attr( $style ) . ' captwiki-widget-' . esc_attr( $this->get_id() ) . '"' . $data_attr . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped

			echo '<div class="captwiki-countdown__timer" role="timer" aria-live="off">';

				$total = count( $active_units );
		foreach ( $active_units as $index => $unit ) {
			$this->captwiki_render_unit( $unit, $settings );

			if ( $show_sep && '' !== trim( (string) $sep_char ) && $index < $total - 1 ) {
				echo '<span class="captwiki-countdown__sep" aria-hidden="true">' . esc_html( $sep_char ) . '</span>';
			}
		}

			echo '</div>';

		if ( 'message' === $expire_action ) {
			echo '<div class="captwiki-countdown__message" hidden>' . wp_kses_post( nl2br( esc_html( $settings['expire_message'] ) ) ) . '</div>';
		}

		echo '</div>';
	}
}
