<?php

/**
 * Class Wiaas_Delivery_Process_Action
 */
class Wiaas_Delivery_Process_Action {

	/**
	 * Check if form is delivery process action form
	 *
	 * @param $form
	 *
	 * @return bool
	 */
	public static function is_action_form($form) {

		$delivery_settings = rgar($form, 'wiaas_delivery_process');

		return  ! empty($delivery_settings) && $delivery_settings['delivery_form_type'] === 'action';
	}

	/**
	 * Retrieve action form for step
	 *
	 * @param Wiaas_Delivery_Process_Step $step
	 *
	 * @return mixed|null
	 */
	public static function get_process_step_action_form($step) {

		if (empty($step->target_form_id)) {

			return null;
		}

		return GFAPI::get_form($step->target_form_id);
	}

	/**
	 * Get action code for delivery process step form
	 *
	 * Action code is used for implementing specific logic for step form
	 *
	 * @param Wiaas_Delivery_Process_Step $step
	 *
	 * @return string
	 */
	public static function get_process_step_action_form_action_code($step) {

		$action_form = self::get_process_step_action_form($step);

		if (empty($action_form)) {

			return 'manual';
		}

		$delivery_settings = rgar($action_form, 'wiaas_delivery_process');

		return empty($delivery_settings) ? 'manual' : $delivery_settings['delivery_action_code'];
	}

	/**
	 * Check if delivery process step has customer acceptance action form
	 *
	 * @param  Wiaas_Delivery_Process_Step $step
	 *
	 * @return bool
	 */
	public static function process_step_has_customer_acceptance_action($step) {

		return self::get_process_step_action_form_action_code($step) === 'customer-acceptance';
	}

	/**
	 * Check if delivery process step has customer validate action form
	 *
	 * @param Wiaas_Delivery_Process_Step $step
	 *
	 * @return bool
	 */
	public static function process_step_has_customer_validate_questionnaires_action($step) {

		return self::get_process_step_action_form_action_code($step) === 'validate-questionnaire';
	}

	/**
	 * @param Wiaas_Delivery_Process_Step $step
	 *
	 * @return array|WP_Error
	 */
	public static function get_process_step_action_entries(Wiaas_Delivery_Process_Step $step) {

		$action_form = self::get_process_step_action_form($step);

		if (!$action_form) {

			return array();
		}

		$search_criteria = array(
			'field_filters' => array(
				array( 'key'   => 'wiaas_delivery_process_id',
				       'value' => $step->get_entry_id()
				),
			),
		);

		$sorting         = array( 'key' => 'date_created', 'direction' => 'DESC' );

		return GFAPI::get_entries( $action_form, $search_criteria, $sorting );
	}

	/**
	 * Retrieve forms that will be used as possible action forms
	 *
	 * @return array
	 */
	public static function get_action_forms() {

		$forms = GFAPI::get_forms();

		$action_forms = array();

		foreach ( $forms as $form ) {

			$delivery_settings = rgar($form, 'wiaas_delivery_process');

			if ( ! empty($delivery_settings) && $delivery_settings['delivery_form_type'] === 'action'){

				$action_forms[] = $form;
			}
		}

		return $action_forms;
	}

	/**
	 * Complete current workflow step for action form
	 *
	 * @param int $action_entry_id
	 */
	public static function complete_action_step($action_entry_id) {

		$action_entry = GFAPI::get_entry($action_entry_id);

		$action_form = GFAPI::get_form($action_entry['form_id']);

		$workflow = new Gravity_Flow_API($action_form['id']);

		$current_step = $workflow->get_current_step($action_entry);

		if ( $current_step ) {

			$new_status = $current_step->get_type() === 'approval' ? 'approved' : 'complete';

			$assignees = $current_step->get_assignees();

			foreach ($assignees as $assignee) {

				$current_step->process_assignee_status($assignee, $new_status, $action_form);
			}
		}

		gravity_flow()->process_workflow($action_form, $action_entry['id']);
	}

	/**
	 * Upload customer questionnaire document
	 *
	 * @param int $action_entry_id
	 */
	public static function upload_customer_questionnaire($action_entry_id) {

		$action_entry = GFAPI::get_entry($action_entry_id);

		$document_field = GFCommon::get_fields_by_type(GFAPI::get_form($action_entry['form_id']), 'wiaas_order_bundle_document')[0];


		$new_file = $document_field->get_single_file_value($action_entry['form_id'], 'file');

		$action_entry[$document_field->id] = $new_file;

		GFAPI::update_entry($action_entry);

		self::complete_action_step($action_entry_id);
	}

	/**
	 * Check if customer uploaded acceptance document
	 *
	 * @param int $action_entry_id
	 *
	 * @return bool
	 */
	public static function is_customer_acceptance_uploaded($action_entry_id) {

		$action_entry = GFAPI::get_entry($action_entry_id);
		$action_form = GFAPI::get_form($action_entry['form_id']);


		$acceptance_documents_field = GFCommon::get_fields_by_type($action_form, 'wiaas_order_document')[0];

		return ! empty( $action_entry[$acceptance_documents_field->id]);
	}

	/**
	 * Update acceptance status for order
	 *
	 * @param int $action_entry_id
	 * @param $new_status
	 * @param $reason
	 */
	public static function update_customer_acceptance_status($action_entry_id, $new_status, $reason) {

		$action_entry = GFAPI::get_entry($action_entry_id);
		$action_form = GFAPI::get_form($action_entry['form_id']);

		$acceptance_field = GFCommon::get_fields_by_type($action_form, 'radio')[0];
		$decline_reason_field = GFCommon::get_fields_by_type($action_form, 'textarea')[0];

		$action_entry[$acceptance_field->id] = $new_status;
		$action_entry[$decline_reason_field->id] = $reason;

		GFAPI::update_entry($action_entry);

		if ($new_status === 'accept') {

			Wiaas_Delivery_Process_Action::complete_action_step($action_entry['id']);
		}
	}

	/**
	 * Upload customer acceptance document for order
	 *
	 * @param int $action_entry_id
	 *
	 * @return bool
	 */
	public static function upload_customer_acceptance_document($action_entry_id) {

		$action_entry = GFAPI::get_entry($action_entry_id);
		$action_form = GFAPI::get_form($action_entry['form_id']);

		$acceptance_documents_field = GFCommon::get_fields_by_type($action_form, 'wiaas_order_document')[0];

		$old_value = $action_entry[$acceptance_documents_field->id];

		$value = $acceptance_documents_field->get_single_file_value($action_form['id'], 'file');

		if ($acceptance_documents_field->multipleFiles ) {

			$value = array( $value );

			$old_value = json_decode( $old_value );

			if (! empty($old_value)) {

				$old_value = is_array( $old_value ) ? $old_value : array( $old_value );

				$value = array_merge( $value, $old_value );
			}

			$value = json_encode( $value );
		}

		$action_entry[$acceptance_documents_field->id] = $value;

		$result = GFAPI::update_entry($action_entry);

		// complete step if current step is customer acceptance user input
		$workflow = new Gravity_Flow_API($action_form['id']);
		$current_step = $workflow->get_current_step($action_entry);

		if ($current_step->get_type() === 'user_input' && ! is_wp_error($result)) {

			Wiaas_Delivery_Process_Action::complete_action_step($action_entry['id']);
		}

		return ! is_wp_error($result);
	}

	/**
	 * Collect customer acceptance action data
	 *
	 * @param int $action_entry_id
	 *
	 * @return array
	 */
	public static function get_customer_acceptance_action_data($action_entry_id) {

		$action_entry = GFAPI::get_entry($action_entry_id);

		$action_form = GFAPI::get_form($action_entry['form_id']);


		$acceptance_documents_field = GFCommon::get_fields_by_type($action_form, 'wiaas_order_document')[0];
		$acceptance_field = GFCommon::get_fields_by_type($action_form, 'radio')[0];
		$decline_reason_field = GFCommon::get_fields_by_type($action_form, 'textarea')[0];
		$expiration_date_field = GFCommon::get_fields_by_type($action_form, 'date')[0];

		$file_paths = json_decode($action_entry[$acceptance_documents_field->id]);

		$documents = array();

		foreach ($file_paths as $file_path) {

			$info = pathinfo( $file_path );

			$documents[] = array(
				'name' => $info['basename'],
				'extension' => $info['extension'],
				'url' => $acceptance_documents_field->get_download_url( $file_path, true )
			);
		}

		$status = 0;
		if ($action_entry[$acceptance_field->id] === 'accept') {
			$status = 1;
		}

		if ($action_entry[$acceptance_field->id] === 'decline') {
			$status = -1;
		}

		return array(
			'action_id' => $action_entry['id'],
			'documents' => $documents,
			'expiration' => $action_entry[$expiration_date_field->id],
			'decline_reason' => $action_entry[$decline_reason_field->id],
			'status' => $status
		);
	}

	/**
	 * Get customer validate questionnaires action data
	 *
	 * @param int $action_entry_id
	 *
	 * @return array|null
	 */
	public static function get_customer_validate_questionnaires_action_data($action_entry_id) {

		$action_entry = GFAPI::get_entry($action_entry_id);

		$action_form = GFAPI::get_form($action_entry['form_id']);

		$order_id = $action_entry['wiaas_delivery_order_id'];
		$order = wc_get_order($order_id);


		// we need to collect document, bundle id and current status
		$bundle_item_id = null; $status = null;

		$bundle_field = GFCommon::get_fields_by_type($action_form, 'wiaas_order_bundle')[0];
		$bundle_item_id = absint(explode('|', $action_entry[$bundle_field->id])[1]);

		if (empty($bundle_item_id)) {

			return null;
		}

		$document_field = GFCommon::get_fields_by_type($action_form, 'wiaas_order_bundle_document')[0];
		$file_path = $action_entry[$document_field->id];

		$info = pathinfo( $action_entry[$document_field->id] );

		$document = array(
			'name' => $info['basename'],
			'extension' => $info['extension'],
			'url' => $document_field->get_download_url( $file_path, true )
		);

		$discussion_field = GFCommon::get_fields_by_type(GFAPI::get_form($action_entry['form_id']), 'workflow_discussion')[0];
		$discussion_items = json_decode($action_entry[$discussion_field->id], ARRAY_A);

		$formatted_comments = array();

		if (is_array($discussion_items)) {
			foreach ($discussion_items as $item) {

				$formatted = $discussion_field->format_discussion_item( $item, 'text', $action_entry_id );
				$formatted = explode("\n", $formatted);

				$formatted_comments[] = array(
					'header' => $formatted[0],
					'value' => $formatted[1]
				);
			}
		}


		$action_workflow_api = new Gravity_Flow_API($action_form['id']);
		$action_step = $action_workflow_api->get_current_step($action_entry);


		// if completed it means that document got validated
		$status = 'validated';

		if (! empty($action_step)) {

			$is_assignee = $action_step->is_assignee($action_step->get_current_assignee_key());

			if ($is_assignee) {
				 // if customer is assignee it means it is his turn to upload changed version of document
				// which means it was rejected
				$status = 'invalid';
			} else {
				// if customer is not assignee it means administrator is still reviewing document
				$status = 'not-validated';
			}
		}

		return array(
			'item_id' => $bundle_item_id,
			'order_id' =>$order->get_id(),
			'action_id' => $action_entry['id'],
			'document' => $document,
			'status' => $status,
			'comments' => $formatted_comments
		);

	}
}
