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

class OsProcessesHelper {


	public static function check_if_process_exists( OsProcessModel $process ): bool {
		$existing_process = new OsProcessModel();
		$existing_process = $existing_process->select( 'id' )->where(
			[
				'event_type' => $process->event_type,
				'name'       => $process->name,
			] 
		)->set_limit( 1 )->get_results();
		return ! empty( $existing_process );
	}

	public static function get_object_data_by_source( string $source, string $value, bool $include_model = true ): array {
		$object_data = [];
		switch ( $source ) {
			case 'booking_id':
				$object_data = [
					'model' => 'booking',
					'id'    => $value,
				];
				if ( $include_model ) {
					$model                      = new OsBookingModel( $value );
					$object_data['model_ready'] = $model;
				}
				break;
			case 'order_id':
				$object_data = [
					'model' => 'order',
					'id'    => $value,
				];
				if ( $include_model ) {
					$model                      = new OsOrderModel( $value );
					$object_data['model_ready'] = $model;
				}
				break;
			case 'payment_request_id':
				$object_data = [
					'model' => 'payment_request',
					'id'    => $value,
				];
				if ( $include_model ) {
					$model                      = new OsPaymentRequestModel( $value );
					$object_data['model_ready'] = $model;
				}
				break;
		}
		/**
		 * Get the list of booking statuses that are enabled for synchronization with Google Calendar
		 *
		 * @since 5.1.0
		 * @hook latepoint_get_process_object_by_source
		 *
		 * @param {array} $object_data Object info
		 * @param {string} $source Source type
		 * @param {string} $value Source value
		 * @param {bool} $include_model Should include model into object data or not
		 *
		 * @returns {array} Filtered object data
		 */
		$object_data = apply_filters( 'latepoint_get_process_object_by_source', $object_data, $source, $value, $include_model );
		return $object_data;
	}

	public static function processes_list_for_select() {
		$processes      = new OsProcessModel();
		$processes      = $processes->get_results_as_models();
		$processes_list = [];
		foreach ( $processes as $process ) {
			$processes_list[] = [
				'value' => $process->id,
				'label' => $process->name,
			];
		}
		return $processes_list;
	}

	public static function extract_trigger_conditions_from_groups( $groups ) {
		$trigger_conditions = [];
		if ( $groups ) {
			foreach ( $groups as $group ) {
				if ( $group['type'] == 'group' && ! empty( $group['trigger_condition'] ) ) {
					$trigger_condition             = [ 'id' => \LatePoint\Misc\ProcessEvent::generate_trigger_condition_id() ];
					$trigger_condition['property'] = $group['trigger_condition']['property'];
					foreach ( $group['items'] as $item ) {
						if ( $item['type'] == 'trigger_condition_branch' ) {
							$trigger_condition['operator'] = $item['settings']['operator'];
							$trigger_condition['value']    = $item['settings']['value'];
						}
						$trigger_conditions[] = $trigger_condition;

						if ( $item['items'] ) {
							$temp = self::extract_trigger_conditions_from_groups( $item['items'] );
							if ( ! empty( $temp ) ) {
								$trigger_conditions = array_merge( $trigger_conditions, $temp );
							}
						}
					}
				}
			}
		}
		return $trigger_conditions;
	}

	/**
	 * @param \LatePoint\Misc\ProcessEvent $event
	 * @return string
	 *
	 * Generate conditions form for an event
	 *
	 */
	public static function trigger_conditions_html_for_event( \LatePoint\Misc\ProcessEvent $event ): string {
		if ( empty( \LatePoint\Misc\ProcessEvent::get_available_trigger_condition_objects_for_event_type( $event->type ) ) ) {
			return '';
		}
		$temp_id         = 'pe_' . \OsUtilHelper::random_text( 'alnum', 6 );
		$conditions_html = '<div class="pe-conditions" id="pe-conditions-for-' . esc_attr( $temp_id ) . '" style="' . ( ( ! empty( $event->trigger_conditions ) ) ? 'display:  block;' : 'display: none;' ) . '">
							            <div class="pe-conditions-heading">' . __( 'Trigger only if:', 'latepoint' ) . '</div>
							            ' . $event->trigger_conditions_form_html() . '
							          </div>';
		$conditions_html = apply_filters( 'latepoint_process_conditions_html', $conditions_html, $event, $temp_id );
		$html            = '<div class="sub-section-row">
	        <div class="sub-section-label">
	          <h3>' . __( 'Conditional', 'latepoint' ) . '</h3>
	        </div>
	        <div class="sub-section-content">
	          ' . OsFormHelper::toggler_field( 'process[event][conditional]', __( 'Trigger only when specific conditions are met', 'latepoint' ), ! empty( $event->trigger_conditions ), 'pe-conditions-for-' . $temp_id ) . '
	          ' . $conditions_html . '
	        </div>
	      </div>';
		return $html;
	}

	public static function time_offset_html_for_event( \LatePoint\Misc\ProcessEvent $event ): string {
		$temp_id = 'pe_' . \OsUtilHelper::random_text( 'alnum', 6 );

		$time_offset_settings_html = OsUtilHelper::pro_feature_block();
		$time_offset_settings_html = apply_filters( 'latepoint_event_time_offset_settings_html', $time_offset_settings_html, $event );

		$html = '<div class="sub-section-row">
	        <div class="sub-section-label">
	          <h3>' . __( 'Time offset', 'latepoint' ) . '</h3>
	        </div>
	        <div class="sub-section-content">
	          ' . OsFormHelper::toggler_field( 'process[event][has_time_offset]', __( 'Execute actions with a time offset', 'latepoint' ), ! empty( $event->time_offset ), 'pe-conditions-for-' . $temp_id ) . '
	          <div class="pe-conditions" id="pe-conditions-for-' . esc_attr( $temp_id ) . '" style="' . ( ( ! empty( $event->time_offset ) ) ? 'display:  block;' : 'display: none;' ) . '">
	            ' . $time_offset_settings_html . '
	          </div>
	        </div>
	      </div>';
		return $html;
	}

	public static function extract_actions_from_groups( $groups ) {
		$actions = [];
		if ( $groups ) {
			foreach ( $groups as $group ) {
				if ( $group['type'] == 'action' ) {
					$action_data = $group['settings'];
					$actions[]   = new \LatePoint\Misc\ProcessAction(
						[
							'type'     => $action_data['type'],
							'id'       => $group['id'],
							'status'   => $action_data['status'] ?? LATEPOINT_STATUS_ACTIVE,
							'settings' => $action_data['settings'],
						] 
					);
				}
				if ( ! empty( $group['items'] ) ) {
					$temp = self::extract_actions_from_groups( $group['items'] );
					if ( ! empty( $temp ) ) {
						$actions = array_merge( $actions, $temp );
					}
				}
			}
		}
		return $actions;
	}

	public static function iterate_trigger_conditions( $trigger_conditions, $actions ) {
		$trigger_condition = reset( $trigger_conditions );
		if ( ! empty( $trigger_conditions ) ) {
			$group = [
				[
					'type'              => 'group',
					'trigger_condition' => [
						'property' => $trigger_condition['property'],
					],
					'items'             => [
						[
							'type'     => 'trigger_condition_branch',
							'settings' => [
								'operator' => $trigger_condition['operator'],
								'value'    => $trigger_condition['value'],
							],
							'items'    => self::iterate_trigger_conditions( array_slice( $trigger_conditions, 1 ), $actions ),
						],
					],
				],
			];
		} else {
			// no more conditions, do actions
			$action_items = [];
			if ( ! empty( $actions ) ) {
				foreach ( $actions as $action_id => $action ) {
					$action_items[] = [
						'type'     => 'action',
						'id'       => $action_id,
						'settings' => [
							'status'   => $action['status'] ?? LATEPOINT_STATUS_ACTIVE,
							'type'     => $action['type'],
							'settings' => $action['settings'] ?? [],
						],
					];
				}
			}
			$group = [
				[
					'type'              => 'group',
					'trigger_condition' => false,
					'items'             => $action_items,
				],
			];
		}
		return $group;
	}

	public static function values_for_trigger_condition_property( $property ) {
		$values             = [];
		$property_data      = explode( '__', $property );
		$property_object    = $property_data[0];
		$property_attribute = $property_data[1];
		switch ( $property_object ) {
			case 'order':
			case 'old_order':
				switch ( $property_attribute ) {
					case 'fulfillment_status':
						$fulfillment_statuses = OsOrdersHelper::get_fulfillment_statuses_list();
						foreach ( $fulfillment_statuses as $fulfillment_status_key => $fulfillment_status ) {
							$values[] = [
								'value' => $fulfillment_status_key,
								'label' => $fulfillment_status,
							];
						}
						break;
					case 'payment_status':
						$payment_statuses = OsOrdersHelper::get_order_payment_statuses_list();
						foreach ( $payment_statuses as $payment_status_key => $payment_status ) {
							$values[] = [
								'value' => $payment_status_key,
								'label' => $payment_status,
							];
						}
						break;
					case 'status':
						$statuses = OsOrdersHelper::get_order_statuses_list();
						foreach ( $statuses as $status_key => $status ) {
							$values[] = [
								'value' => $status_key,
								'label' => $status,
							];
						}
						break;
				}
				break;
			case 'booking':
			case 'old_booking':
				switch ( $property_attribute ) {
					case 'payment_status':
						$payment_statuses = OsOrdersHelper::get_order_payment_statuses_list();
						foreach ( $payment_statuses as $payment_status_key => $payment_status ) {
							$values[] = [
								'value' => $payment_status_key,
								'label' => $payment_status,
							];
						}
						break;
					case 'status':
						$statuses = OsBookingHelper::get_statuses_list();
						foreach ( $statuses as $status_key => $status ) {
							$values[] = [
								'value' => $status_key,
								'label' => $status,
							];
						}
						break;
					case 'agent_id':
						$values = OsFormHelper::model_options_for_multi_select( 'agent' );
						break;
					case 'service_id':
						$values = OsFormHelper::model_options_for_multi_select( 'service' );
						break;
				}
				break;
			case 'customer':
				break;
			case 'transaction':
				switch ( $property_attribute ) {
					case 'payment_method':
						$values = OsPaymentsHelper::get_all_payment_methods_for_select();
						break;
					case 'payment_portion':
						$values = OsPaymentsHelper::get_payment_portions_list();
						break;
					case 'kind':
						$values = OsPaymentsHelper::get_list_of_transaction_kinds();
						break;
					case 'status':
						$values = OsPaymentsHelper::get_transaction_statuses_list();
						break;
				}
				break;
		}

		/**
		 * Returns an array of operators available for a selected condition property
		 *
	 * @since 4.7.0
	 * @hook latepoint_process_event_trigger_condition_properties
		 *
		 * @param {array} $values Array of operators
		 * @param {string} $property Property in a format of object_code__object_property (e.g. old_booking__agent_id)
		 * @param {string} $property_object Object name
		 * @param {string} $property_attribute Property of an object
		 *
		 * @returns {array} The array of available operators
		 *
		 */
		$values = apply_filters( 'latepoint_available_values_for_process_event_trigger_condition_property', $values, $property, $property_object, $property_attribute );
		return $values;
	}
}
