<?php

/**
 * Class Wiaas Delivery Process
 *
 * Adds suport for wiaas order delivery process with integration with Gravity Flow and Gravity Forms
 */
defined( 'ABSPATH' ) || exit;


class Wiaas_Delivery_Process {

	public static function init() {
		self::_register_delivery_process();

		self::_init_hooks();
	}

	private static function _init_hooks() {

        add_action( 'gravityflow_workflow_complete', array(__CLASS__, 'maybe_complete_parent_order'), 10, 2 );
	}

	/**
	 *
	 * Registers our Delivery Process Addons
	 *
	 */
	private static function _register_delivery_process() {
		require_once( 'delivery-process/class-wiaas-delivery-process-addon.php' );
		require_once( 'delivery-process/class-wiaas-delivery-process-action.php' );
		require_once( 'delivery-process/class-wiaas-delivery-process-step-assignee.php' );
		require_once( 'delivery-process/class-wiaas-delivery-process-step.php' );

		// order fields
		require_once( 'delivery-process/class-wiaas-order-fields.php' );

		require_once( 'delivery-process/class-wiaas-field-order-number.php' );
		require_once( 'delivery-process/class-wiaas-field-order-bundle.php' );
		require_once( 'delivery-process/class-wiaas-field-order-installation-select.php' );
		require_once( 'delivery-process/class-wiaas-field-order-bundle-document.php' );
		require_once( 'delivery-process/class-wiaas-field-order-document.php' );
		require_once( 'delivery-process/class-wiaas-field-order-bundle-installation-date.php' );

		// merge tags (for emails)
		require_once( 'delivery-process/class-wiaas-merge-tag-customer-order-url.php' );

		Gravity_Flow_Steps::register( new Wiaas_Delivery_Process_Step() );

		GFAddOn::register( 'Wiaas_Delivery_Process_Addon' );
	}


	public static function create_delivery_process_for_order($order_id, $process_id) {

		$process_form = null;
		$process_form = GFAPI::get_form($process_id);

		if( $process_form ) {

			$new_process_entry = array(
				'wiaas_delivery_order_id' => $order_id,
				'form_id' => $process_id,
			);

			$order_fields = GFCommon::get_fields_by_type($process_form, array('wiaas_order'));


			if (! empty($order_fields)) {

				$order_field = $order_fields[0];

				$new_process_entry[$order_field['id']] = $order_id;
			}

			$process_entry_id = GFAPI::add_entry( $new_process_entry );

			update_post_meta($order_id, 'wiaas_delivery_process_id', $process_id);
			update_post_meta($order_id, 'wiaas_delivery_process_entry_id', $process_entry_id);

			$order = wc_get_order($order_id);

            $order->set_status('processing', 'Started order delivery process.', true);
            $order->save();

			return $process_entry_id;
		}
		return false;
	}

    /**
     * Maybe complete parent order for completed delivery process
     * @param $entry_id
     * @param $form
     */
	public static function maybe_complete_parent_order($entry_id, $form) {

        $entry = GFAPI::get_entry($entry_id);

		$order_id = $entry['wiaas_delivery_order_id'];

        if (!isset($order_id)) {
            return;
        }

        $process_entry_id = get_post_meta($order_id, 'wiaas_delivery_process_entry_id', true);

        // order process entry completed, so complete order
        if (absint($process_entry_id) === absint($entry_id)) {
            $order = wc_get_order($order_id);
            $order->update_status('completed', 'Completed order delivery process.', true);
        }
    }

    public static function get_available_process_list_for_country($country_code) {

		$forms = GFAPI::get_forms();

		$available_process_forms = array();

		foreach ($forms as $form) {

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

			if ($delivery_settings['delivery_form_type'] === 'process' &&
			    $delivery_settings['delivery_country'] === $country_code) {

				$available_process_forms[] = $form;
			}
		}

		return $available_process_forms;
    }


    public static function get_customer_acceptance_data($order_id) {

		$delivery_process_entry = self::get_order_delivery_process_entry($order_id);

	    $data = array();

		if (! empty($delivery_process_entry)) {

			$workflow = new Gravity_Flow_API($delivery_process_entry['form_id']);

			$step = $workflow->get_current_step($delivery_process_entry);

			if ($step && Wiaas_Delivery_Process_Action::process_step_has_customer_acceptance_action($step)) {

				$action_entries = Wiaas_Delivery_Process_Action::get_process_step_action_entries($step);

				$action_entry = $action_entries[0];

				$data[]  = Wiaas_Delivery_Process_Action::get_customer_acceptance_action_data($action_entry['id']);
			}
		}

		return empty( $data ) ? $data : $data[0];
    }

    public static function get_customer_questionnaires_data($order_id) {

	    $data = array();

	    $delivery_process_entry = self::get_order_delivery_process_entry($order_id);

	    if (! empty($delivery_process_entry)) {

		    $workflow = new Gravity_Flow_API($delivery_process_entry['form_id']);

		    $step = $workflow->get_current_step($delivery_process_entry);

		    if ($step && Wiaas_Delivery_Process_Action::process_step_has_customer_validate_questionnaires_action($step)) {

			    $action_entries = Wiaas_Delivery_Process_Action::get_process_step_action_entries($step);

			    foreach ($action_entries as $action_entry) {

				    $action_data = Wiaas_Delivery_Process_Action::get_customer_validate_questionnaires_action_data($action_entry['id']);

				    if (! empty($action_data)) {

					    $data[] = $action_data;
				    }
			    }
		    }

	    }

	    return $data;
    }

    public static function update_customer_acceptance_status($order_id, $status, $reason) {

	    $delivery_process_entry = self::get_order_delivery_process_entry($order_id);

	    if (! empty($delivery_process_entry) ) {

		    $workflow = new Gravity_Flow_API($delivery_process_entry['form_id']);

		    $step = $workflow->get_current_step($delivery_process_entry);

		    $action_entries = Wiaas_Delivery_Process_Action::get_process_step_action_entries($step);

		    $action_entry = $action_entries[0];

		    Wiaas_Delivery_Process_Action::update_customer_acceptance_status($action_entry['id'], $status, $reason);
	    }
    }

    public static function is_customer_acceptance_uploaded($order_id) {

	    $delivery_process_entry = self::get_order_delivery_process_entry($order_id);

	    if (! empty($delivery_process_entry) ) {

		    $workflow = new Gravity_Flow_API($delivery_process_entry['form_id']);

		    $step = $workflow->get_current_step($delivery_process_entry);

		    $action_entries = Wiaas_Delivery_Process_Action::get_process_step_action_entries($step);

		    $action_entry = $action_entries[0];

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

	    return false;
    }

    public static function upload_customer_questionnaire($order_id, $action_entry_id) {

	    Wiaas_Delivery_Process_Action::upload_customer_questionnaire($action_entry_id);
    }

    public static function upload_customer_acceptance_document($order_id) {

		$delivery_process_entry = self::get_order_delivery_process_entry($order_id);

	    if (! empty($delivery_process_entry) ) {

		    $workflow = new Gravity_Flow_API($delivery_process_entry['form_id']);

		    $step = $workflow->get_current_step($delivery_process_entry);

		    $action_entries = Wiaas_Delivery_Process_Action::get_process_step_action_entries($step);

		    $action_entry = $action_entries[0];

		    $success = Wiaas_Delivery_Process_Action::upload_customer_acceptance_document($action_entry['id']);

		    return $success;
	    }

	    return false;
    }


    public static function get_order_delivery_process_entry($order_id) {

		$order = wc_get_order($order_id);

	    $process_entry_id = $order->get_meta('wiaas_delivery_process_entry_id', true);

	    if (empty($process_entry_id)) {

	    	return array();
	    }

	    return GFAPI::get_entry($process_entry_id);
    }

	/**
	 * Retrieves delivery process instance for order
	 *
	 * @param $order_id
	 *
	 * @return array|null
	 */
	public static function get_order_delivery_process($order_id) {

		$process_entry_id = get_post_meta($order_id, 'wiaas_delivery_process_entry_id', true);

		if (empty($process_entry_id)) {
			return null;
		}

		$process_instance = GFAPI::get_entry($process_entry_id);

		$process_form = GFAPI::get_form($process_instance['form_id']);

		$api = new Gravity_Flow_API($process_instance['form_id']);

		$steps_info = $api->get_steps();

		$delivery_process = array(
			'id' => $process_form['id'],
			'name' => $process_form['title'],
			'steps' => array(
				array(
					'short_desc' => 'Order placed',
					'status' => 'complete',
					'order_id' => $order_id,
					'process_id' => $process_entry_id,
					'step_id' => -1,
				),
				array(
					'short_desc' => 'Assign process',
					'status' => 'complete',
					'order_id' => $order_id,
					'process_id' => $process_entry_id,
					'step_id' => 0,
				)
			)
		);

		$current_step = $api->get_current_step($process_instance);

		foreach ( $steps_info as $step_info ) {
			$step = $api->get_step( $step_info->get_id(), $process_instance );

			if (! $step->is_visible_to_customer) {

				continue;
			}

			$action_code = Wiaas_Delivery_Process_Action::get_process_step_action_form_action_code($step);
			$info = $step->get_feed_meta();

			$status = $step->get_status();

			if ($current_step && $current_step->get_id() === $step->get_id()) {
				$status = 'pending';
			}


			$delivery_process['steps'][]      = array(
				'step_id' => $step->get_id(),
				'process_id' => $process_entry_id,
				'short_desc' => $info['step_name'],
				'full_desc' => $info['description'],
				'action_code' => $action_code,
				'status' => $status,
				'order_id' => $order_id,
			);
		}

		return $delivery_process;
	}
}

add_action( 'gravityflow_loaded', array('Wiaas_Delivery_Process', 'init') );
