<?php

/**
 * Handle organization and order level assignment to delivery process step.
 *
 * Currently Gravity Flow enables assignment of roles to step, but these roles are not bounded to organization level
 * so cannot be used in that form for our delivery processes.
 *
 * This will enable delivery process step to be assigned to order admin, order seller, order customer or
 * single order supplier organization.
 *
 *
 * Class Wiaas_Delivery_Process_Step_Assignee
 */

class Wiaas_Delivery_Process_Step_Assignee {

	public static function init() {

		add_filter('gravityflow_assignee_choices', array (__CLASS__, 'filter_delivery_process_step_assignee_choices'));

		add_filter('gravityflow_step_assignees', array (__CLASS__, 'maybe_handle_order_organization_assignees'), 10, 2);
	}


	/**
	 * Allow only order specific organization roles and fields as choices for delivery process step assignee
	 *
	 * @param array $old_choices
	 *
	 * @return array
	 */
	public static function filter_delivery_process_step_assignee_choices($old_choices) {

		$choices = array(
			$choices[] = array(
				'label'   => __( 'Order', 'wiaas' ),
				'choices' => array(
					array(
						'value' => 'role|administrator', // allow global administrator role here since it is only one
						'label' => __('Administrator', 'wiaas')
					)
				),
			)
		);

		// add administrator users
		$args            = array(
			'number' => 1000,
			'orderby' => 'display_name',
			'role' => 'administrator'
		);
		$accounts        = get_users( $args );
		$account_choices = array();
		foreach ( $accounts as $account ) {
			$account_choices[] = array( 'value' => 'user_id|' . $account->ID, 'label' => $account->display_name );
		}

		$choices[] = array(
			'label'   => __( 'Users', 'gravityflow' ),
			'choices' => $account_choices,
		);

		// append field choices
		foreach ($old_choices as $old_choice) {

			if ($old_choice['label'] === 'Fields') {

				$choices[] = $old_choice;
				break;
			}
		}

		return $choices;
	}


	/**
	 * Handle order level assignees for delivery process step
	 *
	 * @param $assignees
	 *
	 * @param Gravity_Flow_Step $step
	 *
	 * @return array
	 */
	public static function maybe_handle_order_organization_assignees($assignees, Gravity_Flow_Step $step) {

		$mapped_assignees = array();

		$order_id = self::_get_order_id_for_step($step);

		$order = wc_get_order($order_id);

		foreach ($assignees as $assignee) {

			/**
			 * Handle step assignee for installation company field
			 */
			if (strpos($assignee->get_type(), 'wiaas_installation_') !== false) {

				$item_id = $assignee->get_id();

				$item = $order->get_item($item_id);

				$organization_id = $item['wiaas_supplier_organization_id'];

				$user_ids = wiaas_get_organization_user_ids($organization_id);

				if (empty($user_ids)) {

					continue;
				}

				$user_id = $user_ids[0];

				$mapped_assignees[] = $step->get_assignee( array(
					'id' => $user_id,
					'type' => 'user_id',
					'editable_fields' => $assignee->get_editable_fields()
				) );

				continue;
			}

			/**
			 * Handle step assignee for order role
			 */
			if ($assignee->get_type() === 'wiaas_order_role') {


				$order_role = $assignee->get_id();

				// Assign step to order customer
				if ($order_role === 'customer') {

					$customer_user_id = $order->get_customer_id();

					// for now assign only customer that create order
					// check if all customer organization users should be able to see order step

					$mapped_assignees[] = $step->get_assignee( array(
						'id' => $customer_user_id,
						'type' => 'user_id',
						'editable_fields' => $assignee->get_editable_fields()
					) );

					continue;
				}
			}

			$mapped_assignees[] = $assignee;
		}

		return $mapped_assignees;
	}


	/**
	 * Retrieve order id for delivery process step
	 *
	 * @param Gravity_Flow_Step $step
	 *
	 * @return bool|int Order id on success, false if step does not have associated order id
	 *
	 */
	private static function _get_order_id_for_step(Gravity_Flow_Step $step) {

		$entry = $step->get_entry();

		// if order is present in entry metadata use that value
		if (! empty($entry['wiaas_delivery_order_id'])) {

			return absint($entry['wiaas_delivery_order_id']);
		}

		// try getting order id from order field
		$form = GFAPI::get_form($entry['form_id']);

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

		if (! empty($order_fields)) {

			$order_field = $order_fields[0]; // there should only be one order field per entry

			return absint($entry[$order_field->id]);
		}

		return false;
	}
}

Wiaas_Delivery_Process_Step_Assignee::init();
