<?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 {

	private static $process_form_title_prefix = 'DELIVERY PROCESS:';

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

		self::_init_hooks();
	}

	private static function _init_hooks() {
		add_action('woocommerce_new_order', array( __CLASS__, 'create_delivery_process_for_order' ));

		add_filter( 'gform_entry_meta', array(__CLASS__, 'extend_gravity_form_entry_meta'), 10, 2 );
		add_action( 'gravityflow_workflow_complete', array(__CLASS__, 'maybe_complete_parent_process_step'), 5, 3 );

        add_action( 'gravityflow_workflow_complete', array(__CLASS__, 'maybe_complete_parent_order'), 10, 3 );

        // Some temporary functions to make inbox page prettier
        add_filter('gravityflow_inbox_submitter_name', array(__CLASS__, 'display_step_name_in_inbox'), 10, 3);
        add_filter('gravityflow_approve_label_workflow_detail', array(__CLASS__, 'approval_step_approval_label'), 10, 2);
        add_filter('gravityflow_reject_label_workflow_detail', array(__CLASS__, 'approval_step_reject_label'), 10, 2);
	}

	public static function approval_step_approval_label($label, $step) {
	    if ($step->get_name() === 'Complete step') {
            return esc_html__( 'Complete step', 'wiaas' );
        }
        return $label;
    }

    public static function approval_step_reject_label($label, $step) {
        if ($step->get_name() === 'Complete step') {
            return esc_html__( 'Cancel', 'wiaas' );
        }
        return $label;
    }

    public static function display_step_name_in_inbox($name, $entry, $form) {
        return $entry['wiaas_delivery_step_name'];
    }

	/**
	 * Registers our Delivery Process Step Type as available Gravity Flow Step Type
	 */
	private static function _register_delivery_process_step_type() {
		require_once( 'delivery-process/class-wiaas-delivery-process-step.php' );

		Gravity_Flow_Steps::register( new Wiaas_Delivery_Process_Step() );
	}

    /**
     * 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) === $entry_id) {
            $order = wc_get_order($order_id);
            $order->update_status('completed', 'Completed order delivery process.', true);
        }
    }

	/**
	 * 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');
		if (!isset($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()
		);

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

			$info = $step->get_feed_meta();
			$delivery_process['steps'][]      = array(
				'step_id' => $step->get_id(),
				'step_form_entry_id' => $step->get_target_form_entry_id() ?: null,
				'short_desc' => $info['step_name'],
				'full_desc' => $info['description'],
				'action_code' => $step->get_delivery_action_type(),
				'step_type' => $step->get_delivery_action_type() === 'manual' ? 'manual' : 'extraAction',
				'status' => $step->get_status() ?: 'inactive',
				'order_id' => $order_id,
				'actual_date' => $step->get_target_actual_date(),
				'comments' => $step->get_target_step_comments(),
			);
		}

		return $delivery_process;
	}

	/**
	 * Automatically create delivery process instance when order is created
	 * @param $order_id
	 */
	public static function create_delivery_process_for_order($order_id) {
		$process_form = null;
		$forms = GFFormsModel::search_forms( self::$process_form_title_prefix, true );
		$process_form = $forms[0];
		if(isset($process_form)) {
			$order = wc_get_order( $order_id );
			$new_process_entry = array(
				'form_id' => $process_form->id,
				'2' => $order->get_customer_id(),
				'wiaas_delivery_order_id' => $order_id,
			);
			$process_entry_id = GFAPI::add_entry( $new_process_entry );

			add_post_meta($order_id, 'wiaas_delivery_process_id', $process_form->id);
			add_post_meta($order_id, 'wiaas_delivery_process_entry_id', $process_entry_id);
		}
	}

	/**
	 * Extends Gravity Form entry metadata with 'wiaas_delivery_process_id'
	 *
	 * This way we can track for each delivery step its parent process
	 * @param $entry_meta
	 *
	 * @return mixed
	 */
	public static function extend_gravity_form_entry_meta($entry_meta) {
		$entry_meta[ 'wiaas_delivery_process_id' ] = array(
			'label'                      => 'Wiaas Delivery Process Id',
			'is_numeric'                 => true,
			'update_entry_meta_callback' => null,
			'is_default_column'          => false, // this column will be displayed by default on the entry list
			'filter'                     => array(
				'operators' => array( 'is' ),
			),
		);

		$entry_meta[ 'wiaas_delivery_order_id' ] = array(
			'label'                      => 'Wiaas Delivery Process Order Id',
			'is_numeric'                 => true,
			'update_entry_meta_callback' => null,
			'is_default_column'          => false, // this column will be displayed by default on the entry list
			'filter'                     => array(
				'operators' => array( 'is' ),
			),
		);

        $entry_meta[ 'wiaas_delivery_step_name' ] = array(
            'label'                      => 'Wiaas Delivery Step name',
            'is_numeric'                 => false,
            'update_entry_meta_callback' => null,
            'is_default_column'          => false, // this column will be displayed by default on the entry list
            'filter'                     => array(
                'operators' => array( 'is' ),
            ),
        );

		return $entry_meta;
	}

	/**
	 * Process parent process when single step workflow has completed
	 * @param $entry_id
	 * @param $form
	 * @param $final_status
	 */
	public static function maybe_complete_parent_process_step($entry_id, $form) {
		$entry = GFAPI::get_entry($entry_id);
		$parent_entry_id = $entry['wiaas_delivery_process_id'];

		if (empty($parent_entry_id)) {
			return false;
		}

		$parent_entry_id = absint( $parent_entry_id );
		$parent_entry = GFAPI::get_entry( $parent_entry_id );

		$parent_api = new Gravity_Flow_API( $parent_entry['form_id'] );
		$parent_api->process_workflow( $parent_entry_id );
	}
}

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