<?php

class Wiass_REST_Delivery_Process_API {

	const BASE_NAME = WP_HOME . '/';

	const FILE_KEY_NAME = 'file';

	const PATH_PARTS_TO_EXTRACT = 7;
	
	const ACCEPTANCE_STATUS_FIELD_ID = 8;
	const EXPIRATION_DATE_FIELD_ID = 9;
	const DECLINE_REASON_FIELD_ID = 10;
	const UPLOADED_FILES_FIELD_ID = 12;

	const USER_INPUT_STEP_NAME = 'Upload acceptance file';
	const ACCEPT_STATUS_LABEL = 'accept';
	const DECLINE_STATUS_LABEL = 'decline';

	const ACCEPTABLE_STATUS = [self::ACCEPT_STATUS_LABEL, self::DECLINE_STATUS_LABEL];
	
	/**
	 * Endpoint namespace.
	 *
	 * @var string
	 */
	private static $namespace = 'wiaas';


	public static function register_routes() {
		register_rest_route( self::$namespace, 'next-delivery-steps', array(
			'methods' => 'GET',
			'callback' => array(__CLASS__, 'get_next_actions_for_user'),
		) );

		register_rest_route( self::$namespace, 'customer-acceptance/(?P<entry_id>\d+)', array(
			'methods' => 'GET',
			'callback' => array(__CLASS__, 'get_customer_acceptance'),
			'permission_callback' => 'is_user_logged_in'
		) );

		register_rest_route( self::$namespace, 'customer-acceptance/(?P<entry_id>\d+)', array(
			'methods' => 'POST',
			'callback' => array(__CLASS__, 'submit_customer_acceptance'),
			'permission_callback' => 'is_user_logged_in'
		) );

		register_rest_route( self::$namespace, 'customer-acceptance/(?P<entry_id>\d+)/upload-file' , array(
			'methods' => 'POST',
			'callback' => array(__CLASS__, 'upload_file'),
			'permission_callback' => 'is_user_logged_in'
		) );
	}

	public static function get_next_actions_for_user() {
		$current_user = wp_get_current_user();

		$field_filters   = array();
		$field_filters[] = array(
			'key'   => 'workflow_user_id_' . $current_user->ID,
			'value' => 'pending',
		);

		$user_roles = gravity_flow()->get_user_roles();
		foreach ( $user_roles as $user_role ) {
			$field_filters[] = array(
				'key'   => 'workflow_role_' . $user_role,
				'value' => 'pending',
			);
		}

		$field_filters['mode'] = 'any';

		$search_criteria                  = array();
		$search_criteria['field_filters'] = $field_filters;
		$search_criteria['status']        = 'active';

		$form_ids = gravity_flow()->get_workflow_form_ids();

		$total_count = 7;


		$entries = GFAPI::get_entries( $form_ids, $search_criteria, null, null, $total_count );

		$data = array();
		foreach ($entries as $entry) {
			$step = gravity_flow()->get_step( $entry['workflow_step'] );
			$data[] = array(
				'order_id' => $entry['wiaas_delivery_order_id'],
				'order_number' => $entry['wiaas_delivery_order_id'],
				'status' => $entry['workflow_final_status'],
				'step_action' => $step->get_name(),
			);
		}

		return rest_ensure_response($data);
	}

	public static function get_customer_acceptance(WP_REST_Request $request){
		$entry = GFAPI::get_entry($request['entry_id']);
		if (is_wp_error($entry)){
			return wiaas_api_generate_error('Customer acceptance entry not found', 404);
		}

		$acceptance_documents = array();
		$uploaded_files = json_decode($entry[self::UPLOADED_FILES_FIELD_ID]);

		foreach($uploaded_files as $file_url){
			//example of decoded url : 
			//http://localhost/wp/index.php?gf-download=2018/08/rokovi-1535378841.docx&form-id=1&field-id=12&hash=1be6c30f0eeff93563b352d15fe459d5ded12ee06c2c8f36fed66b42dedf2534
			
			$decoded_url = urldecode($file_url);			
			$url_parts = explode('?', $decoded_url);
			$file_name_base_parts = explode('&', $url_parts[1]);
			$file_name_parts = explode('/', $file_name_base_parts[0]);
			$file_name_with_extension_parts = explode('.', $file_name_parts[2]);

			$acceptance_documents_entry = array(
				'name' => $file_name_with_extension_parts[0],
				'extension' => $file_name_with_extension_parts[1],
				'url' => $file_url
			);
			array_push($acceptance_documents, $acceptance_documents_entry);
		}

		$acceptance_status = 0;
		if ($entry[self::ACCEPTANCE_STATUS_FIELD_ID]){
			$acceptance_status = ($entry[self::ACCEPTANCE_STATUS_FIELD_ID] === 'accept') ? 1 : -1;
		}

		return rest_ensure_response(array(
			'documents' => $acceptance_documents,
			'expiration' => $entry[self::EXPIRATION_DATE_FIELD_ID],
			'status' => $acceptance_status,
			'decline_reason' => $entry[self::DECLINE_REASON_FIELD_ID]
		));
	}

	public static function submit_customer_acceptance(WP_REST_Request $request){
		$entry = GFAPI::get_entry($request['entry_id']);
		if (is_wp_error($entry)){
			return wiaas_api_generate_error('Customer acceptance entry not found', 404);
		}

		$status = $request['actionType'];
		$reason = $request['declineReason'];

		if (!in_array($status, self::ACCEPTABLE_STATUS)){
			return wiaas_api_notice('ACCEPTANCE_STATUS_MISSING', 'error');
		}

		$installation_declined = ($status === self::DECLINE_STATUS_LABEL);

		$uploaded_files = json_decode($entry[self::UPLOADED_FILES_FIELD_ID]);

		if ($installation_declined && $reason === ''){
			return wiaas_api_notice('DECLINE_REASON_EMPTY', 'error');
		}

		if (!$installation_declined && (count($uploaded_files)===0)){
			return wiaas_api_notice('ACCEPTANCE_NOT_UPLOADED', 'error');
		}

		$entry[self::DECLINE_REASON_FIELD_ID] = $reason;
		$entry[self::ACCEPTANCE_STATUS_FIELD_ID] = $status;

		if (!GFAPI::update_entry( $entry )){
			return wiaas_api_notice('INTERNAL_SERVER_ERROR', 'error');
		}

		//Check if step is already completed, to not submit again 
		$gf_api = new Gravity_Flow_API($entry['form_id']);
		$current_step = $gf_api->get_current_step($entry);
		if ($current_step->get_name() !== self::USER_INPUT_STEP_NAME){
			return wiaas_api_notice('ACCEPTANCE_STATUS_UPDATED', 'success');
		}

		if ( $current_step ) {
			$current_step->purge_assignees();
			$current_step->update_step_status( 'complete' );
		}
		$entry_id = $entry['id'];
		$new_step_id = $current_step->get_id() + 1;
		$new_step = $gf_api->get_step( $new_step_id, $entry );
		$feedback = sprintf( esc_html__( 'Sent to step: %s', 'gravityflow' ), $new_step->get_name() );
		$gf_api->add_timeline_note( $entry_id, $feedback );
		$gf_api->log_activity( 'workflow', 'sent_to_step', $gf_api->form_id, $entry_id, $step_id );
		gform_update_meta( $entry_id, 'workflow_final_status', 'pending' );
		$new_step->start();
		$gf_api->process_workflow( $entry_id );
	

		if ($installation_declined){
			return wiaas_api_notice('INSTALLATION_DECLINED', 'success');
		}
		return wiaas_api_notice('INSTALLATION_ACCEPTED', 'success');
	}

	public static function upload_file(WP_REST_Request $request){
		$files = $request->get_file_params();
		if (!$files[self::FILE_KEY_NAME]){
			return wiaas_api_notice('NO_FILES_UPLOADED', 'error');
		}

		$entry = GFAPI::get_entry($request['entry_id']);
		if (is_wp_error($entry)){
			return wiaas_api_generate_error('Customer acceptance entry not found', 404);
		}

		$form = GFAPI::get_form($entry['form_id']);
		$form_upload_path = GFFormsModel::get_upload_path( $form['id'] );

		$target_path = $form_upload_path . '/' . date('Y') . '/' . date('m') . '/';
		wp_mkdir_p( $target_path );
		GFCommon::recursive_add_index_file( $target_path );

		$upload_file_field = GFAPI::get_field($form['id'], self::UPLOADED_FILES_FIELD_ID);
		$file_name = sanitize_file_name($files[self::FILE_KEY_NAME]['name']);
		$file_path_details = pathinfo($file_name);
		
		if ( GFCommon::file_name_has_disallowed_extension( $file_name ) ) {
			return wiaas_api_notice('INVALID_FILE_ACCEPTANCE', 'error');
		}
		$allowed_extensions = ! empty( $upload_file_field->allowedExtensions ) ? GFCommon::clean_extensions( explode( ',', strtolower( $upload_file_field->allowedExtensions ) ) ) : array();
		if ( ! empty( $allowed_extensions ) ) {
			if ( ! GFCommon::match_file_extension( $file_name, $allowed_extensions ) ) {
				return wiaas_api_notice('INVALID_FILE_ACCEPTANCE', 'error');
			}
		}

		$new_file_name = $file_path_details['filename'] . '-' . time() . '.' . $file_path_details['extension'];

		// Bypasses security checks when running unit tests.
		if ( defined( 'WP_TEST_IN_PROGRESS' ) && WP_TEST_IN_PROGRESS ) {
			return wiaas_api_notice('FILE_UPLOADED', 'success');
		}

		if ( move_uploaded_file($files[self::FILE_KEY_NAME]['tmp_name'], $target_path . $new_file_name ) ) {
			GFFormsModel::set_permissions( $target_path . $new_file_name );
		} else {
			return wiaas_api_notice('INTERNAL_SERVER_ERROR', 'error');
		}

		//Extract path relative to the root
		//Last 6 strings (excluding last empty) are path relative to the root 
		$path_parts = explode('/', $target_path);
		
		$relative_path = '';
		$i = count($path_parts) - self::PATH_PARTS_TO_EXTRACT;
		while($i < count($path_parts)-1){
			$relative_path = $relative_path . $path_parts[$i] . '/';
			$i++;
		}

		$file_url = self::BASE_NAME . $relative_path . $new_file_name;
		$url_for_download = $upload_file_field->get_download_url($file_url);

		$uploaded_files = json_decode($entry[self::UPLOADED_FILES_FIELD_ID]);
		
		if ($uploaded_files === NULL){
			$uploaded_files = [];
		}
		array_push($uploaded_files, $url_for_download);

		$entry[self::UPLOADED_FILES_FIELD_ID] = json_encode($uploaded_files);

		if (GFAPI::update_entry( $entry )) {
			return wiaas_api_notice('FILE_UPLOADED','success');
		}

		return wiaas_api_notice('NOT_UPLOADED', 'error');
	}
}