[Back]
<?php
/*
 * Copyright (c) 2022 LatePoint LLC. All rights reserved.
 */

namespace LatePoint\Misc;

class ProcessAction{
	public string $id;
	public string $type = 'send_email';
	public string $status = 'active';
	public ?array $settings = [];
	public array $prepared_data_for_run = [];
	public array $replacement_vars = [];
	public array $selected_data_objects = []; // example ['model' => 'booking', 'id' => INT]
	public ProcessEvent $event;

	function __construct($args = []){
		$allowed_props = self::allowed_props();
		foreach($args as $key => $arg){
			if(in_array($key, $allowed_props)) $this->$key = $arg;
		}
		if(empty($this->id)) $this->id = self::generate_id();
		switch($this->type){
			case 'send_email':
				$this->settings['to_email'] = $this->settings['to_email'] ?? '';
				$this->settings['subject'] = $this->settings['subject'] ?? '';
				$this->settings['content'] = $this->settings['content'] ?? '';
				break;
			case 'send_sms':
				$this->settings['to_phone'] = $this->settings['to_phone'] ?? '';
				$this->settings['content'] = $this->settings['content'] ?? '';
				break;
			case 'send_whatsapp':
				$this->settings['to_phone'] = $this->settings['to_phone'] ?? '';
				$this->settings['content'] = $this->settings['content'] ?? '';
				break;
		}
	}

	public function is_attach_calendar(  ) {
		return !empty($this->settings['attach_calendar']) && \OsUtilHelper::is_on($this->settings['attach_calendar']);
	}

	public function get_nice_type_name(){
		return self::get_action_name_for_type($this->type);
	}

	public function get_descriptive_setting(){
		switch($this->type) {
			case 'send_email':
				return $this->settings['to_email'] ?? '';
			case 'send_sms':
				return $this->settings['to_phone'] ?? '';
			case 'send_whatsapp':
				return $this->settings['to_phone'] ?? '';
		}
	}

	public function generate_replacement_vars(){
		$this->replacement_vars = \OsReplacerHelper::generate_replacement_vars_from_data_objects($this->selected_data_objects);
	}

	public function set_from_params($params){
		if(!empty($params['id'])) $this->id = $params['id'];
		if(!empty($params['type'])) $this->type = $params['type'];
		if(!empty($params['settings'])) $this->settings = $params['settings'];
		if(!empty($params['event'])) $this->event = new ProcessEvent(['type' => $params['event']['type']]);
	}

	public function load_settings_from_template($template_id){
		$templates = \OsNotificationsHelper::load_templates_for_action_type($this->type);
		foreach($templates as $template){
			if($template['id'] == $template_id){
				switch($this->type){
					case 'send_email':
						$this->settings['to_email'] = $template['to_email'];
						$this->settings['subject'] = $template['subject'];
						$this->settings['content'] = $template['content'];
						break;
					case 'send_sms':
						$this->settings['to_phone'] = $template['to_phone'];
						$this->settings['content'] = $template['content'];
						break;
					case 'send_whatsapp':
						$this->settings['to_phone'] = $template['to_phone'];
						$this->settings['content'] = $template['content'];
						break;
				}

				/**
				 * Returns an array of process action settings, based on a selected template
				 *
				 * @since 4.7.0
				 * @hook latepoint_process_action_settings
				 *
				 * @param {array} $settings Array of settings to filter
				 * @param {array} $template Array of data representing selected template
				 * @param {ProcessAction} $action Instance of <code>ProcessAction</code> for which settings are being generated
				 *
				 * @returns {array} Filtered array of process action settings
				 */
				$this->settings = apply_filters('latepoint_process_action_settings', $this->settings, $template, $this);
				break;
			}
		}
	}

	public static function generate_form(ProcessAction $action, string $process_id = ''): string{
		$descriptive_setting = $action->get_descriptive_setting() ? '<div class="process-action-descriptive-setting">'.$action->get_descriptive_setting().'</div>' : '';
		$html = '<div class="process-action-form pa-type-'.$action->type.' pa-status-'.$action->status.'" data-id="'.$action->id.'">';
			$html.= '<div class="process-action-heading">
								<div class="process-action-status"></div>
								<div class="process-action-icon"></div>
								<div class="process-action-name">'.self::get_action_name_for_type($action->type).'</div>
								'.$descriptive_setting.'
								<div class="process-action-chevron"><i class="latepoint-icon latepoint-icon-chevron-down"></i></div>
								<a href="#" class="process-action-remove os-remove-process-action" 
										data-os-prompt="'.__('Are you sure you want to delete this action?', 'latepoint').'"><i class="latepoint-icon latepoint-icon-cross"></i></a>
							</div>';
			$html.= '<div class="process-action-content">';
			$html.= '<div class="os-row">';
			$html.= \OsFormHelper::select_field('process[actions]['.$action->id.'][type]', __('Action Type', 'latepoint'), \LatePoint\Misc\ProcessAction::get_action_types_for_select(), $action->type, ['class' => 'process-action-type', 'data-action-id' => $action->id, 'data-process-id' => $process_id, 'data-route' => \OsRouterHelper::build_route_name('processes', 'load_action_settings')], ['class' => 'os-col-10']);
			$html.= \OsFormHelper::select_field('process[actions]['.$action->id.'][status]', __('Status', 'latepoint'), [LATEPOINT_STATUS_ACTIVE => __('Active', 'latepoint'), LATEPOINT_STATUS_DISABLED => __('Disabled', 'latepoint')], $action->status, false, ['class' => 'os-col-2']);
			$html.= '</div>';
			$html.= '<div class="process-action-settings">';
				$html.= self::generate_settings_fields($action, $process_id);
			$html.= '</div>';
			$html.= '<div class="process-buttons">
								<a href="#" class="latepoint-btn latepoint-btn-danger pull-left os-remove-process-action" 
									data-os-prompt="'.__('Are you sure you want to delete this action?', 'latepoint').'" >'.__('Delete', 'latepoint').'</a>
								<a href="#" data-route="'.\OsRouterHelper::build_route_name('processes', 'action_test_preview').'" class="latepoint-btn latepoint-btn-secondary os-run-process-action" ><i class="latepoint-icon latepoint-icon-play-circle"></i><span>'.__('Test this action', 'latepoint').'</span></a>
							</div>';
			$html.= '</div>';
		$html.= '</div>';
		return $html;
	}


	public static function generate_settings_fields(ProcessAction $action, string $process_id = ''){
		$html = '';

		if(in_array($action->type, ['send_email', 'send_sms'])){
			$html.= '<div class="process-action-controls-wrapper">';
			$html.= '<a href="#" data-os-after-call="latepoint_init_template_library" data-os-params="'.\OsUtilHelper::build_os_params(['action_id'=>$action->id, 'action_type'=>$action->type, 'process_id' => $process_id]).'" data-os-lightbox-classes="width-1000" data-os-action="'.\OsRouterHelper::build_route_name('notifications', 'templates_index').'" href="#" data-os-output-target="side-panel" class="latepoint-btn latepoint-btn-outline latepoint-btn-sm"><i class="latepoint-icon latepoint-icon-book"></i><span>'.__('Load from template', 'latepoint').'</span></a>';
			$html.= '<a href="#" class="latepoint-btn latepoint-btn-outline latepoint-btn-sm open-template-variables-panel"><i class="latepoint-icon latepoint-icon-zap"></i><span>'.__('Show smart variables', 'latepoint').'</span></a>';
			$html.= '</div>';
		}

		switch($action->type){
			case 'send_email':
				$html.= '<div class="os-row">';
				$html.= \OsFormHelper::text_field('process[actions]['.$action->id.'][settings][to_email]', __('To Email', 'latepoint'),  $action->settings['to_email'], ['theme' => 'simple', 'placeholder' => __('To email address', 'latepoint')], ['class' => 'os-col-6']);
				$html.= \OsFormHelper::text_field('process[actions]['.$action->id.'][settings][subject]', __('Email Subject', 'latepoint'),  $action->settings['subject'], ['theme' => 'simple', 'placeholder' => __('Email Subject', 'latepoint')], ['class' => 'os-col-6']);
				$html.= '</div>';
				$html.= \OsFormHelper::textarea_field('process[actions]['.$action->id.'][settings][content]', false, $action->settings['content'], ['id' => 'process_actions_'.$action->id.'_settings_content', 'class' => 'os-wp-editor-textarea']);
				$html.= \OsFormHelper::toggler_field('process[actions]['.$action->id.'][settings][attach_calendar]', __('Attach Booking Calendar', 'latepoint'), $action->is_attach_calendar());
				$html.= \OsFormHelper::multiple_files_uploader_field('process[actions]['.$action->id.'][settings][attachments]', esc_html__( '+ Attach File', 'latepoint' ), esc_html__( 'Remove File', 'latepoint' ), $action->get_attachments() );
				break;
			case 'send_sms':
				if(\OsSmsHelper::get_sms_processors()){
					$html.= \OsFormHelper::text_field('process[actions]['.$action->id.'][settings][to_phone]', __('To Phone Number', 'latepoint'),  $action->settings['to_phone'], ['theme' => 'simple', 'placeholder' => __('Phone Number', 'latepoint')]);
					$html.= \OsFormHelper::textarea_field('process[actions]['.$action->id.'][settings][content]', __('Message Content', 'latepoint'),  $action->settings['content'], ['theme' => 'simple', 'placeholder' => __('Message', 'latepoint'), 'rows' => 4]);
				}else{
					$html = \OsUtilHelper::generate_missing_addon_link(__('You have to enable an SMS processor to send text messages. Available in a premium version.', 'latepoint'));
				}
				break;
			case 'send_whatsapp':
				if(\OsWhatsappHelper::get_whatsapp_processors()){
					$html.= '<div class="latepoint-whatsapp-templates-loader" data-route="'.esc_attr(\OsRouterHelper::build_route_name('whatsapp', 'load_templates_for_action')).'" data-selected-template-id="'.esc_attr($action->settings['template_id'] ?? '').'" data-process-id="'.esc_attr($process_id).'" data-process-action-id="'.esc_attr($action->id).'"></div>';
					$html.= '<div class="latepoint-whatsapp-templates-holder">'.\OsFormHelper::get_hidden_fields_for_array($action->settings, 'process[actions]['.$action->id.']').'</div>';

				}else{
					$html = \OsUtilHelper::generate_missing_addon_link(__('You have to enable a WhatsApp processor to send messages. Available in a premium version.', 'latepoint'));
				}
				break;
			case 'trigger_webhook':
				$html = \OsUtilHelper::generate_missing_addon_link(__('Requires upgrade to a premium version', 'latepoint'));
				break;
		}

		/**
	    * Filters HTML code (after) for Process Action settings form
		*
	    * @since 4.7.0
	    * @hook latepoint_process_action_settings_fields_html_after
	    *
	    * @param {string} $html HTML content of the settings form
	    * @param {ProcessAction} $action ProcessAction object for which this settings form is being generated
	    *
	    * @returns {string} HTML content of the settings form
	    */
		return apply_filters('latepoint_process_action_settings_fields_html_after', $html, $action);
	}

	public static function generate_id(): string{
  	return 'pa_'.\OsUtilHelper::random_text('alnum', 6);
  }

	public function settings_form(){
		$html = '';
		switch($this->type){
			case 'send_email':
				$html.= \OsFormHelper::text_field('action[actions]['.$this->id.'][to]', '', $this->settings['to'], ['theme' => 'simple', 'placeholder' => __('Email To', 'latepoint')]);
				break;
			case 'send_sms':
				$html.= \OsFormHelper::text_field('action[actions]['.$this->id.'][to]', '', $this->settings['to'], ['theme' => 'simple', 'placeholder' => __('SMS To', 'latepoint')]);
				break;
			case 'send_whatsapp':
				$html.= \OsFormHelper::text_field('action[actions]['.$this->id.'][to]', '', $this->settings['to'], ['theme' => 'simple', 'placeholder' => __('WhatsApp Message To', 'latepoint')]);
				break;
			case 'trigger_webhook':
				$html.= \OsFormHelper::text_field('action[actions]['.$this->id.'][url]', '', $this->settings['url'], ['theme' => 'simple', 'placeholder' => __('Webhook URL', 'latepoint')]);
				break;
		}

		return apply_filters('latepoint_process_action_settings_form_html', $html, $this);
	}


	public static function get_action_types(){
		$action_types = ['send_email', 'send_sms', 'trigger_webhook', 'send_whatsapp'];

		/**
		 * Returns an array of process action types that can be executed when an event is triggered
		 *
		 * @since 4.7.0
		 * @hook latepoint_process_action_types
		 *
		 * @param {array} $action_types Array of action types to filter
		 *
		 * @returns {array} Filtered array of action types
		 */
		return apply_filters('latepoint_process_action_types', $action_types);
	}

	public static function get_action_name_for_type($type){
		$names = [
			'send_email' => __('Send Email', 'latepoint'),
			'send_sms' => __('Send SMS', 'latepoint'),
			'trigger_webhook' => __('HTTP Request (Webhook)', 'latepoint'),
			'send_whatsapp' => __('Send WhatsApp Message', 'latepoint')
		];

		/**
		 * Returns an array of process action types mapped to their displayable names
		 *
		 * @since 4.7.0
		 * @hook latepoint_process_action_names
		 *
		 * @param {array} $names Array of action types/names to filter
		 *
		 * @returns {array} Filtered array of action types/names
		 */
		$names = apply_filters('latepoint_process_action_names', $names);

		return $names[$type] ?? __('n/a', 'latepoint');
	}

	public static function get_action_types_for_select(){
		$types = self::get_action_types();
		$types_for_select = [];
		foreach($types as $type){
			$types_for_select[$type] = self::get_action_name_for_type($type);
		}
		return $types_for_select;
	}

	public function prepare_data_for_run(){
		$this->generate_replacement_vars();
		foreach($this->selected_data_objects as $data_object){
			switch($data_object['model']) {
				case 'order':
					$this->prepared_data_for_run['activity_data']['order_id'] = $data_object['id'];
					if(!empty($data_object['model_ready'])){
						$this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['model_ready']->customer_id;
					}
					break;
				case 'booking':
					$this->prepared_data_for_run['activity_data']['booking_id'] = $data_object['id'];
					if(!empty($data_object['model_ready'])){
						$this->prepared_data_for_run['activity_data']['agent_id'] = $data_object['model_ready']->agent_id;
						$this->prepared_data_for_run['activity_data']['service_id'] = $data_object['model_ready']->service_id;
						$this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['model_ready']->customer_id;
					}
					break;
				case 'customer':
					$this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['id'];
					break;
				case 'transaction':
					$this->prepared_data_for_run['activity_data']['transaction_id'] = $data_object['id'];
					break;
				case 'payment_request':
					$this->prepared_data_for_run['activity_data']['payment_request_id'] = $data_object['id'];
					break;
			}
		}

		$this->replacement_vars['sender_type'] = $this->type;

		switch($this->type) {
			case 'send_email':
				$this->prepared_data_for_run['to'] = \OsReplacerHelper::replace_all_vars($this->settings['to_email'], $this->replacement_vars);
				$this->prepared_data_for_run['subject'] = \OsReplacerHelper::replace_all_vars($this->settings['subject'], $this->replacement_vars);
				$this->prepared_data_for_run['content'] = \OsReplacerHelper::replace_all_vars($this->settings['content'], $this->replacement_vars);
				$this->prepared_data_for_run['attachments'] = [];

				if ($this->is_attach_calendar()) {
					$booking = $this->find_booking_from_selected_data();

					if ($booking) {
						$ical_temp_file = $this->create_ical_temp_file($booking);

						if ($ical_temp_file) {
							$this->prepared_data_for_run['attachments'][] = $ical_temp_file;
							$this->prepared_data_for_run['_attachments_temp_files'] = [$ical_temp_file];
						}
					}
				}
				$attachments = $this->get_attachments();
				if (!empty($attachments)) {
					foreach ( $attachments as $attachment_id ) {
						$file_path = get_attached_file($attachment_id);
						if ($file_path && file_exists($file_path)) {
							$this->prepared_data_for_run['attachments'][] = $file_path;
						} else {
							\OsDebugHelper::log('Attachment file not found: ' . $file_path, 'error');
						}
					}
				}

				break;
			case 'send_sms':
				$this->prepared_data_for_run['to'] = \OsReplacerHelper::replace_all_vars($this->settings['to_phone'], $this->replacement_vars);
				$this->prepared_data_for_run['content'] = \OsReplacerHelper::replace_all_vars($this->settings['content'], $this->replacement_vars);
				break;
			case 'send_whatsapp':
				$this->prepared_data_for_run['to'] = \OsReplacerHelper::replace_all_vars($this->settings['to_phone'], $this->replacement_vars);
				$this->prepared_data_for_run['data']['type'] = 'template';
				$this->prepared_data_for_run['data']['template_id'] = $this->settings['template_id'];
				$this->prepared_data_for_run['data']['template_language'] = $this->settings['template_language'];
				$this->prepared_data_for_run['data']['template_parameter_format'] = $this->settings['template_parameter_format'];
				$this->prepared_data_for_run['data']['template_category'] = $this->settings['template_category'];
				$this->prepared_data_for_run['data']['template_name'] = $this->settings['template_name'];

				$selected_template = \OsWhatsappHelper::get_template($this->settings['template_id']);

				$this->prepared_data_for_run['data']['variables'] = $this->settings['variables'] ?? [];
				if(!empty($this->settings['variables'])){
					foreach($this->settings['variables'] as $type => $variables){
						$parameters = [];
						foreach($variables as $key => $value){
							$clean_key = str_replace(['{{', '}}'], '', $key);
							$replaced_value = \OsReplacerHelper::replace_all_vars($value, $this->replacement_vars);
							if(is_numeric($clean_key)){
								$parameters[] = ['type' => 'text', 'text' => $replaced_value];
							}else{
								$parameters[] = ['type' => 'text', 'text' => $replaced_value, 'parameter_name' => $clean_key];
							}
						}
						if(strtolower($type) == 'buttons'){
							// each button has to have a separate component element, only URL typed buttons have variables in them
							foreach($parameters as $index => $parameter){
								$this->prepared_data_for_run['data']['components'][] = [
									'type' => 'button',
									'index' => $index,
									'sub_type' => 'url',
									'parameters' => $parameters
								];
							}
						}else{
							$this->prepared_data_for_run['data']['components'][] = ['type' => $type, 'parameters' => $parameters];
						}
					}
				}

				$content_by_type['header'] = \OsWhatsappHelper::get_template_component_value_by_key($selected_template, 'HEADER', 'text');
				$content_by_type['body'] = \OsWhatsappHelper::get_template_component_value_by_key($selected_template, 'BODY', 'text');
				$content_by_type['buttons'] = \OsWhatsappHelper::get_template_component_value_by_key($selected_template, 'BUTTONS', 'buttons');


				foreach($content_by_type as $content_type => $content){
					if($content_type == 'buttons'){
						if(!empty($content)){
							foreach($content as $button){
								// only URL can have variables
								if($button['type'] == 'URL') $button['url'] = empty($this->settings['variables'][$content_type]) ? $button['url'] : \OsReplacerHelper::replace_all_vars(str_replace(array_keys($this->settings['variables'][$content_type]), array_values($this->settings['variables'][$content_type]), $button['url']), $this->replacement_vars);
								$this->prepared_data_for_run['content_for_'.$content_type][] = $button;
							}
						}else{
							$this->prepared_data_for_run['content_for_'.$content_type] = [];
						}
					}else{
						$this->prepared_data_for_run['content_for_'.$content_type] = empty($this->settings['variables'][$content_type]) ? $content : \OsReplacerHelper::replace_all_vars(str_replace(array_keys($this->settings['variables'][$content_type]), array_values($this->settings['variables'][$content_type]), $content), $this->replacement_vars);
					}
				}
				break;
		}

		/**
		 * Prepare data for action run
		 *
		 * @since 4.7.0
		 * @hook latepoint_process_prepare_data_for_run
		 *
		 * @param {ProcessAction} $action ProcessAction that was executed
		 *
		 * @returns {ProcessAction} $action ProcessAction with prepared data for action run
		 */
		return apply_filters('latepoint_process_prepare_data_for_run', $this);
	}


	/**
	 * @param $prepare_data
	 * @return array [status => '', 'message' => '']
	 */
	public function run($prepare_data = true){
		$result = [
			'status' => LATEPOINT_STATUS_SUCCESS,
			'message' => __('Nothing to run', 'latepoint')
		];
		if($prepare_data) $this->prepare_data_for_run();

		switch($this->type) {
			case 'send_email':
				$notification_type = 'email';
				$result = \OsNotificationsHelper::send($notification_type, $this->prepared_data_for_run);
				break;
			case 'send_sms':
				$notification_type = 'sms';
				$result = \OsNotificationsHelper::send($notification_type, $this->prepared_data_for_run);
				break;
			case 'send_whatsapp':
				$notification_type = 'whatsapp';
				$result = \OsNotificationsHelper::send($notification_type, $this->prepared_data_for_run);
				break;
		}

		$tmp_files = $this->prepared_data_for_run['_attachments_temp_files'] ?? [];
		foreach ( $tmp_files as $tmp_file ) {
			if ( file_exists( $tmp_file ) ) {
				@unlink( $tmp_file );
			};
		}

		/**
		 * ProcessAction run result
		 *
		 * @since 4.7.0
		 * @hook latepoint_process_action_run
		 *
		 * @param {array} $result The array of data describing the status of the action run
		 * @param {ProcessAction} $action ProcessAction that was executed
		 *
		 * @returns {array}  The array of descriptive data, possibly transformed by additional hooked ProcessAction handlers
		 */
		return apply_filters('latepoint_process_action_run', $result, $this);
	}


	/**
	 * @return string
	 */
	public function generate_preview(){
		if(empty($this->prepared_data_for_run)){
			$this->prepare_data_for_run();
			// nothing was generated, probably because there is no object attached
			if(empty($this->prepared_data_for_run)) return '<div class="action-preview-error">'.__('You have to create a booking to be able to test this action.', 'latepoint').'</div>';
		}
		$html = '<div class="action-preview-content-wrapper">';
		$preview_content_html = '';
		switch($this->type){
			case 'send_email':
				$preview_content_html.= '<div class="action-preview-subject"><span class="os-label">'.__('Subject:', 'latepoint').'</span> '.$this->prepared_data_for_run['subject'].'</div>';
				$preview_content_html.= '<div class="action-preview-to"><span class="os-label">'.__('To:', 'latepoint').'</span><span class="os-value">'.esc_html($this->prepared_data_for_run['to']).'</div>';
				$preview_content_html.= '<div class="action-preview-content">'.$this->prepared_data_for_run['content'].'</div>';
				break;
			case 'send_sms':
				$preview_content_html.= '<div class="action-preview-to"><span class="os-label">'.__('To:', 'latepoint').'</span><span class="os-value">'.esc_html($this->prepared_data_for_run['to']).'</span></div>';
				$preview_content_html.= '<div class="action-preview-content">'.$this->prepared_data_for_run['content'].'</div>';
				break;
			case 'send_whatsapp':
				$preview_content_html.= '<div class="action-preview-to"><span class="os-label">'.__('To:', 'latepoint').'</span><span class="os-value">'.esc_html($this->prepared_data_for_run['to']).'</span></div>';
				$preview_content_html.= '<div class="action-preview-content">';
					$preview_content_html.= '<div class="latepoint-whatsapp-template-preview-messages">';
						$preview_content_html.= '<div class="latepoint-whatsapp-template-preview-message">';
						$preview_content_html.= '<div class="latepoint-whatsapp-template-preview-message-header">'.$this->prepared_data_for_run['content_for_header'].'</div>';
						$preview_content_html.= '<div class="latepoint-whatsapp-template-preview-message-body">'.$this->prepared_data_for_run['content_for_body'].'</div>';
						if($this->prepared_data_for_run['content_for_buttons']){
							$preview_content_html.= '<div class="latepoint-whatsapp-template-preview-message-buttons">';
							foreach($this->prepared_data_for_run['content_for_buttons'] as $button){
								switch($button['type']){
									case 'PHONE_NUMBER':
										$preview_content_html.= '<a href="tel:'.esc_url($button['phone_number']).'" class="latepoint-whatsapp-template-preview-message-button"><i class="latepoint-icon latepoint-icon-phone"></i>'.esc_html($button['text']).'</a>';
										break;
									case 'URL':
										$preview_content_html.= '<a href="'.esc_url($button['url']).'" class="latepoint-whatsapp-template-preview-message-button"><i class="latepoint-icon latepoint-icon-external-link"></i>'.esc_html($button['text']).'</a>';
										break;
								}
							}
							$preview_content_html.= '</div>';
						}
						$preview_content_html.= '</div>';
					$preview_content_html.= '</div>';
				$preview_content_html.= '</div>';
				break;
		}

		/**
		 * Generates a preview html for ProcessAction testing
		 *
		 * @since 4.7.0
		 * @hook latepoint_process_action_generate_preview
		 *
		 * @param {string} $preview_content_html HTML that goes inside of a preview
		 * @param {ProcessAction} $action ProcessAction that is being tested
		 *
		 * @returns {string} HTML that goes inside of a preview
		 */
		$preview_content_html = apply_filters('latepoint_process_action_generate_preview', $preview_content_html, $this);
		$html.= $preview_content_html;
		$html.= '</div>';
		return $html;
	}

	private function find_booking_from_selected_data() {
		foreach ($this->selected_data_objects as $data_object) {
			if ($data_object['model'] === 'booking' && !empty($data_object['model_ready'])) {
				return $data_object['model_ready'];
			}
		}
		return null;
	}

	private function create_ical_temp_file( $booking ) {
		try {
			$ical_content = \OsBookingHelper::generate_ical_event_string( $booking );
			if ( empty( $ical_content ) ) {
				throw new \Exception( 'iCal content is empty' );
			}

			$temp_file = tempnam(sys_get_temp_dir(), 'latepoint_ical_');
			$ical_temp_file = $temp_file . '.ics';
			rename($temp_file, $ical_temp_file);

			if ( file_put_contents( $ical_temp_file, $ical_content ) !== false ) {
				return $ical_temp_file;
			} else {
				throw new \Exception( 'Failed to write iCal content to file' );
			}
		} catch ( \Exception $e ) {
			\OsDebugHelper::log( 'Failed to create iCal file: ' . $e->getMessage(), 'error' );
		}

		return null;
	}

	public static function replace_variables($test){

	}

	public static function allowed_props(): array{
		return ['id', 'type', 'settings', 'status'];
	}

	public function get_attachments() {
		return !empty($this->settings['attachments']) ? explode(',', $this->settings['attachments']) : [];
	}
}