<?php 

class API {
	public function __construct () {
		$this->register_routes();
	}
	public function register_routes () {
		// ***************************************************************************
		// Surveys
		// ***************************************************************************

		// register_rest_route('bwsurvey/v1', '/survey/', array(
		// 	'methods' => 'GET',
		// 	'callback' => array($this, 'route_surveys'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// register_rest_route('bwsurvey/v1', '/survey/', array(
		// 	'methods' => 'POST',
		// 	'callback' => array($this, 'route_create_survey'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)', array(
			'methods' => 'GET',
			'callback' => array($this, 'route_survey')
		));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)', array(
		// 	'methods' => 'PUT',
		// 	'callback' => array($this, 'route_update_survey'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)', array(
		// 	'methods' => 'DELETE',
		// 	'callback' => array($this, 'route_delete_survey'),
		// 	'permission_callback' => array($this, 'permission')
		// ));


		// ***************************************************************************
		// Notifications
		// ***************************************************************************

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/notification', array(
		// 	'methods' => 'GET',
		// 	'callback' => array($this, 'route_notifications')
		// ));

		register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/notification', array(
			'methods' => 'POST',
			'callback' => array($this, 'route_create_notification'),
			'permission_callback' => array($this, 'permission')
		));

		register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/notification/(?P<notification_id>\d+)', array(
			'methods' => 'GET',
			'callback' => array($this, 'route_notification'),
			'permission_callback' => array($this, 'permission')
		));

		register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/notification/(?P<notification_id>\d+)', array(
			'methods' => 'PUT',
			'callback' => array($this, 'route_update_notification'),
			'permission_callback' => array($this, 'permission')
		));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/notification/(?P<notification_id>\d+)', array(
		// 	'methods' => 'DELETE',
		// 	'callback' => array($this, 'route_delete_notification'),
		// 	'permission_callback' => array($this, 'permission')
		// ));


		// ***************************************************************************
		// Confirmations
		// ***************************************************************************

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/confirmation', array(
		// 	'methods' => 'GET',
		// 	'callback' => array($this, 'route_confirmations'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/confirmation', array(
		// 	'methods' => 'POST',
		// 	'callback' => array($this, 'route_create_confirmation'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/confirmation/(?P<confirmation_id>\d+)', array(
		// 	'methods' => 'GET',
		// 	'callback' => array($this, 'route_confirmation'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/confirmation/(?P<confirmation_id>\d+)', array(
		// 	'methods' => 'PUT',
		// 	'callback' => array($this, 'route_update_confirmation'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/confirmation/(?P<confirmation_id>\d+)', array(
		// 	'methods' => 'DELETE',
		// 	'callback' => array($this, 'route_delete_confirmation'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// ***************************************************************************
		// Entries
		// ***************************************************************************
		register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/newentry', array(
			'methods' => 'GET',
			'callback' => array($this, 'route_entry_new'),
			'permission_callback' => '__return_true'
		));

		register_rest_route('bwsurvey/v1', '/entry/(?P<entry_id>\d+)/submit', array(
			'methods' => 'POST',
			'callback' => array($this, 'route_entry_submit'),
			'permission_callback' => '__return_true'
		));

		register_rest_route('bwsurvey/v1', '/entry/(?P<entry_id>\d+)/section', array(
			'methods' => 'POST',
			'callback' => array($this, 'route_entry_section'),
			'permission_callback' => '__return_true'
		));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/entry', array(
		// 	'methods' => 'GET',
		// 	'callback' => array($this, 'route_entries'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/entry', array(
		// 	'methods' => 'POST',
		// 	'callback' => array($this, 'route_create_entry'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/entry/(?P<entry_id>\d+)', array(
		// 	'methods' => 'GET',
		// 	'callback' => array($this, 'route_entry'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/entry/(?P<entry_id>\d+)', array(
		// 	'methods' => 'PUT',
		// 	'callback' => array($this, 'route_update_entry'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/entry/(?P<confirmation_id>\d+)', array(
		// 	'methods' => 'DELETE',
		// 	'callback' => array($this, 'route_delete_confirmation'),
		// 	'permission_callback' => array($this, 'permission')
		// ));

		// ***************************************************************************
		// Reports
		// ***************************************************************************
		register_rest_route('bwsurvey/v1', '/survey/(?P<survey_id>\d+)/reports', array(
			'methods' => 'GET',
			'callback' => array($this, 'reports'),
			'permission_callback' => array($this, 'permission')
		));
	}


	// *******************************************************************************
	// permission callback
	// *******************************************************************************

	public function permission () {
		return true;
		return current_user_can('edit_posts');
	}

	// *******************************************************************************
	//
	// Routes
	//
	// *******************************************************************************

	// Surveys ***********************************************************************

	public function route_survey ( $request ) {
		$survey_id = intval($request['survey_id']);
		global $wpdb;

		$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}bwsurvey_surveys WHERE id=%d", $survey_id));
		if ($wpdb->last_error || empty($results)) {
			return new WP_Error('bw_survey_no_survey', __('Invalid survey'), array('status' => 404));
		}

		$survey = $results[0];

		$survey->data = unserialize($survey->data);

		return (array) $survey;
	}


	// Notifications *****************************************************************

	public function route_notification ( $request ) {
		$survey_id = intval( $request['survey_id'] );
		$notification_id = intval( $request['notification_id'] );

		global $wpdb;

		$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}bwsurvey_notifications WHERE id=%d", $notification_id));
		if ($wpdb->last_error || empty($results)) {
			return new WP_Error('bw_survey_no_notification', __('Invalid notification'), array('status' => 404));
		}

		$notification = $results[0];

		$notification->data = unserialize($notification->data);

		return (array) $notification;
	}

	public function route_create_notification ( $request ) {
		$notification = $request->get_json_params();

		global $wpdb;

		$wpdb->query(
			$wpdb->prepare(
				"INSERT INTO {$wpdb->prefix}bwsurvey_notifications (survey_id, type, data) VALUES (%d, %s, %s)",
				[
					$notification['survey_id'],
					$notification['type'],
					serialize( $notification['data'] )
				]
			)
		);
		if ( $wpdb->last_error ) {
			return new WP_Error('bw_survey_notification_create_failed', __('Failed to create notification'), array('status' => 500));
		}

		$notification['id'] = $wpdb->insert_id;

		return $notification;
	}

	public function route_update_notification ( $request ) {
		$notification = $request->get_json_params();

		global $wpdb;

		$wpdb->query(
			$wpdb->prepare(
				"UPDATE {$wpdb->prefix}bwsurvey_notifications SET type=%s, data=%s WHERE id = %d",
				[
					$notification['type'],
					serialize( $notification['data'] ),
					$notification['id']
				]
			)
		);
		if ( $wpdb->last_error ) {
			return new WP_Error('bw_survey_notification_update_failed', __('Failed to update notification'), array('status' => 500));
		}

		return $notification;
	}

	// Confirmations *****************************************************************

	// Entries ***********************************************************************

	public function route_entry_new ($request) {
		$survey_id = intval($request['survey_id']);
		global $wpdb;
		$table = $wpdb->prefix . 'bwsurvey_entries';
		$data = array('survey_id' => $survey_id, 'data' => serialize(array()));
		$format = array('%d','%s');
		$wpdb->insert($table,$data,$format);
		$entry_id = $wpdb->insert_id;

		$result = new WP_REST_Response(array(
			'id' => $entry_id,
			'survey_id' => $survey_id,
			'data' => (object) array(),
		), 200);

		$result->set_headers(array('Cache-Control' => 'no-cache, must-revalidate, max-age=0, no-store, private'));

		return $result;
	}

	public function route_entry_submit ($request) {
		$entry_id = intval($request['entry_id']);
		global $wpdb;
		$data = $request->get_json_params();

		$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}bwsurvey_entries WHERE id=%d", $entry_id));
		if ($wpdb->last_error) {
			return new WP_Error('bw_survey_no_entry', __('Invalid entry'), array('status' => 404));
		}

		$entry = $results[0];

		$entry->data = array_replace(
			unserialize($entry->data),
			$data
		);

		$survey_id = $entry->survey_id;
		$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}bwsurvey_surveys WHERE id=%d", $survey_id));
		if ($wpdb->last_error || empty($results)) {
			return new WP_Error('bw_survey_no_survey', __('Invalid survey'), array('status' => 404));
		}
		$survey = $results[0];
		$survey->data = unserialize($survey->data);

		$entry = apply_filters('bw_survey_entry', (array) $entry, (array) $survey);
		$entry['submitted'] = true;

		do_action('bw_survey_notifications', $entry, (array) $survey);

		$results = $wpdb->get_results($wpdb->prepare("SELECT notification_id FROM {$wpdb->prefix}bwsurvey_sent_notifications WHERE entry_id=%d", $entry_id));
		if ($wpdb->last_error) {
			return new WP_Error('internal_server_error', __('Internal server error'), array('status' => 500));
		}
		$entry['sent'] = array();
		foreach ($results as $sent) {
			$entry['sent'][] = $sent->notification_id;
		}

		$wpdb->update(
			$wpdb->prefix . 'bwsurvey_entries',
			array('data' => serialize($entry['data']), 'submitted' => 1),
			array('id' => $entry_id),
			array('%s', '%d'),
			array('%d')
		);
		return array(
			'confirmation' => apply_filters('bw_survey_confirmation', '<p>Thank You!</p>', $entry, (array) $survey)
		);
	}

	public function route_entry_section ($request) {
		$entry_id = intval($request['entry_id']);
		global $wpdb;
		$data = $request->get_json_params();

		$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}bwsurvey_entries WHERE id=%d", $entry_id));
		if ($wpdb->last_error) {
			return new WP_Error('bw_survey_no_entry', __('Invalid entry'), array('status' => 404));
		}

		$entry = $results[0];

		$entry->data = array_replace(
			unserialize($entry->data),
			$data
		);

		$survey_id = $entry->survey_id;
		$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}bwsurvey_surveys WHERE id=%d", $survey_id));
		if ($wpdb->last_error || empty($results)) {
			return new WP_Error('bw_survey_no_survey', __('Invalid survey'), array('status' => 404));
		}
		$survey = $results[0];
		$survey->data = unserialize($survey->data);

		$entry = apply_filters('bw_survey_entry', (array) $entry, (array) $survey);
		$entry['submitted'] = $entry['submitted'] == "1" ? true : false;

		do_action('bw_survey_notifications', $entry, (array) $survey);

		$results = $wpdb->get_results($wpdb->prepare("SELECT notification_id FROM {$wpdb->prefix}bwsurvey_sent_notifications WHERE entry_id=%d", $entry_id));
		if ($wpdb->last_error) {
			return new WP_Error('internal_server_error', __('Internal server error'), array('status' => 500));
		}
		$entry['sent'] = array();
		foreach ($results as $sent) {
			$entry['sent'][] = $sent->notification_id;
		}

		$wpdb->update(
			$wpdb->prefix . 'bwsurvey_entries',
			array('data' => serialize($entry['data'])),
			array('id' => $entry_id),
			array('%s'),
			array('%d')
		);

		return $entry;
	}

	public function reports ($request) {
		$survey_id = intval($request['survey_id']);
		$start = $request->get_param( 'start' );
		$end = $request->get_param( 'end' );

		global $wpdb;

		$survey = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}bwsurvey_surveys WHERE id = %d", $survey_id ) );
		if ( empty($survey) ) {
			return new WP_Error('bw_survey_no_survey', __('Invalid survey'), array('status' => 404));
		}
		$survey_data = unserialize($survey->data);

		$where = $wpdb->prepare(
			" WHERE survey_id = %d",
			array( $survey_id )
		);

		if ( ! empty( $start ) ) {
			$where .= $wpdb->prepare(
				" AND created_on >= %s",
				array( $start . ' 00:00:00' )
			);
		}

		if ( ! empty( $end ) ) {
			$where .= $wpdb->prepare(
				" AND created_on <= %s",
				array( $end . ' 23:59:59' )
			);
		}

		$count = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}bwsurvey_entries " . $where );
		$limit = 40;
		$page = 0;

		$report = array();
		$submitted_total = 0;
		$not_submitted_total = 0;

		while ( $page * $limit < $count ) {
			$entries = $wpdb->get_results( $wpdb->prepare(
				"SELECT * FROM {$wpdb->prefix}bwsurvey_entries" . $where . " LIMIT %d OFFSET %d",
				array( $limit, $limit * $page )
			) );

			$page += 1;

			foreach ( $entries as $entry ) {

				$entry_data = unserialize($entry->data);
				if ( empty( $entry_data ) ) {
					continue;
				}
				if ( $entry->submitted ) {
					$submitted_total++;
				} else {
					$not_submitted_total++;
				}

				foreach ( $survey_data['sections'] as $section ) {
					foreach ( $section as $question ) {
						if ( ! isset( $entry_data[$question] ) ) {
							continue;
						}

						if ( ! isset( $report[$question] ) ) {
							if ( $survey_data['fields'][$question]['type'] === 'text' ) {
								$report[$question] = array(
									'submitted_total' => 0,
									'not_submitted_total' => 0
								);
							} else {
								$report[$question] = array(
									'submitted_total' => 0,
									'submitted' => array(),
									'not_submitted_total' => 0,
									'not_submitted' => array()
								);
							}
						}

						$report[$question][$entry->submitted ? 'submitted_total' : 'not_submitted_total'] += 1;

						if ( $survey_data['fields'][$question]['type'] === 'text' ) {
							continue;
						}
						
						if ( ! isset( $report[$question][$entry->submitted ? 'submitted' : 'not_submitted'][$entry_data[$question]] ) ) {
							$report[$question][$entry->submitted ? 'submitted' : 'not_submitted'][$entry_data[$question]] = 0;
						}
						$report[$question][$entry->submitted ? 'submitted' : 'not_submitted'][$entry_data[$question]] += 1;
					}
				}
			}
		}

		return array(
			'survey' => $survey_data,
			'report' => $report,
			'submitted_entry_total' => $submitted_total,
			'not_submitted_entry_total' => $not_submitted_total,
			'survey_id' => $survey_id,
			'survey_title' => $survey->title,
			'start' => $start,
			'end' => $end
		);
	}
}
