<?php
/**
 * FE Admin Coupons Bulk Emails controller.
 *
 * @since 2.2.0
 */

declare( strict_types=1 );
namespace FeData\FastEvents\RestAPI\Public;

defined( 'ABSPATH' ) || exit;

use DateTime;
use Exception;
use FeData\FastEvents\Helpers\AuthHelper;
use FeData\FastEvents\Mail\MailerFactory;
use FeData\FastEvents\Storage\Options;
use FeData\FastEvents\Storage\PluginSettings;
use FeData\FastEvents\Utilities\CheckHtml;
use FeData\FastEvents\Utilities\TimeUtil;
use stdClass;
use WP_Error;
use WP_REST_Controller;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

/**
 * FE Admin Coupons Bulk Emails class.
 */
class BulkCouponsController extends WP_REST_Controller {

	/**
	 * The maximum size of the request buffer with order_ids.
	 *
	 * @since 2.2.0
	 * @var int
	 */
	private int $batch_size;

	/**
	 * Admin Coupons Bulk Emails constructor.
	 *
	 * @param AuthHelper     $auth     The auth helper.
	 * @param Options        $options  The options.
	 * @param PluginSettings $settings The plugin settings.
	 * @param MailerFactory  $mailer   The mailer factory.
	 *
	 * @since 2.0
	 */
	public function __construct(
		private readonly AuthHelper $auth,
		private readonly Options $options,
		private readonly PluginSettings $settings,
		private readonly MailerFactory $mailer
	) {
		$this->namespace  = 'fast-events/v1';
		$this->rest_base  = 'admin/coupons/bulk/emails';
		$this->batch_size = $this->settings->as_batch_size();
	}


	/**
	 * Register the routes for the objects of the controller.
	 *
	 * @since 2.2.0
	 */
	public function register_routes(): void {

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/list',
			array(
				array(
					'methods'             => WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'create_item' ),
					'permission_callback' => function () {
						return $this->fast_events_admin_permissions( $this->auth::COUPON_BULK_EMAIL );
					},
					'args'                => $this->get_endpoint_args_for_item_schema(),
				),
				'schema' => array( $this, 'get_public_item_schema' ),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/send',
			array(
				array(
					'methods'             => WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'update_item' ),
					'permission_callback' => function () {
						return $this->fast_events_admin_permissions( $this->auth::COUPON_BULK_EMAIL );
					},
					'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
				),
				'schema' => array( $this, 'get_public_item_schema' ),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/send-example',
			array(
				array(
					'methods'             => WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'send_example' ),
					'permission_callback' => function () {
						return $this->fast_events_admin_permissions( $this->auth::COUPON_BULK_EMAIL );
					},
					'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
				),
				'schema' => array( $this, 'get_public_item_schema' ),
			)
		);
	}


	/**
	 * Get the authorization for the Coupons Bulk Emails endpoints.
	 *
	 * @param int $action The action on the controller.
	 * @return WP_Error|bool
	 *
	 * @since 2.2.0
	 */
	public function fast_events_admin_permissions( int $action ): WP_Error|bool {
		return $this->auth->authorize( $action );
	}


	/**
	 * Generate a list of: - coupon ids (the source = 1) that meet the conditions
	 *                     - the event ids (the source = 0) of the selected events
	 *
	 * @param WP_REST_Request $request Full details about the request.
	 * @return WP_REST_Response|WP_Error|bool|array Response object on success, or WP_Error object on failure.
	 *
	 * @since 2.2.0
	 */
	public function create_item( $request ): WP_Error|WP_REST_Response|bool|array {
		global $wpdb;

		// Subject or body empty?
		if ( empty( $request['subject'] ) || empty( $request['body'] ) ) {
			return new WP_Error( 'missing_param', __( 'Subject or body is empty', 'fast-events' ), array( 'status' => 400 ) );
		}

		// Do we need to check all events?
		$events = $this->fast_events_tools_check_events( $request['event_ids'] ?? null );

		// Look up the user group ids if this is the source.
		if ( '0' === $request['bulk_source'] ) {

			// Is the template code available?
			if ( empty( $request['template_code'] ) ) {
				return new WP_Error( 'no_template', __( 'No coupon template provided', 'fast-events' ), array( 'status' => 400 ) );
			}
			$result = $wpdb->get_var( 'SELECT EXISTS(SELECT * FROM ' . $wpdb->prefix . 'fe_event_coupons WHERE code="' . $request['template_code'] . '")' ); // phpcs:ignore
			if ( ! $result ) {
				return new WP_Error( 'not_found', __( 'Coupon template not found', 'fast-events' ), array( 'status' => 400 ) );
			}

			// Return the number of email addresses in the user groups.
			$result = $wpdb->get_col( 'SELECT MAX(id) FROM ' . $wpdb->prefix . 'fe_event_user_groups ' . $events . ' GROUP BY email' ); // phpcs:ignore
		} else {

			// The source is now the coupons table.
			$response = $wpdb->get_results(
				'SELECT id, code, start_date, end_date, events, minimum_tickets, maximum_tickets, ' .
				'minimum_amount, maximum_amount, email FROM ' . $wpdb->prefix . 'fe_event_coupons'
			);
			$result   = $this->filter_coupons( $request, $response );
		}

		// No result?
		if ( empty( $result ) ) {
			return new WP_Error( 'not_found', __( 'No entries found', 'fast-events' ), array( 'status' => 404 ) );
		}

		$request->set_param( 'context', 'view' );

		return rest_ensure_response( $this->prepare_item_for_response( $result, $request ) );
	}


	/**
	 * Send email to a list of order ids.
	 *
	 * @param WP_REST_Request $request Full details about the request.
	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
	 *
	 * @since 2.2.0
	 */
	public function update_item( $request ): WP_Error|WP_REST_Response {

		if ( ! isset( $request['ids'] ) ) {
			return new WP_Error( 'missing_param', __( 'No ids found', 'fast-events' ), array( 'status' => 400 ) );
		}

		// Subject or body empty?
		if ( empty( $request['subject'] ) || empty( $request['body'] ) ) {
			return new WP_Error( 'missing_param', __( 'Subject or body is empty', 'fast-events' ), array( 'status' => 400 ) );
		}

		// Get the batch of ids.
		$ids = array_map( 'absint', $request['ids'] );

		// Check if the batchsize is not exceeded.
		if ( $this->batch_size < count( $ids ) ) {
			return new WP_Error( 'wrong_batch_size', __( 'Wrong batch size', 'fast-events' ), array( 'status' => 400 ) );
		}

		if ( '0' === $request['bulk_source'] ) {
			$response = $this->send_closed_user_group_emails( $request );
		} else {
			$response = $this->send_coupon_emails( $request );
		}
		if ( is_wp_error( $response ) ) {
			return $response;
		}

		return rest_ensure_response( array( 'errors' => $response ) );
	}


	/**
	 * Send an example email.
	 *
	 * @param WP_REST_Request $request Full details about the request.
	 * @return WP_REST_Response|WP_Error|bool|array Response object on success, or WP_Error object on failure.
	 *
	 * @since 2.2.0
	 */
	public function send_example( WP_REST_Request $request ): WP_Error|WP_REST_Response|bool|array {

		// Subject or body empty?
		if ( empty( $request['subject'] ) || empty( $request['body'] ) ) {
			return new WP_Error( 'missing_param', __( 'Subject or body is empty', 'fast-events' ), array( 'status' => 400 ) );
		}

		// Check the emailaddress.
		if ( ! isset( $request['email'] ) ) {
			if ( ! is_email( $request['email'] ) ) {
				return new WP_Error( 'invalid_email', __( 'Invalid emailaddress', 'fast-events' ), array( 'status' => 400 ) );
			}
		}

		// Boot the HTML Purifier.
		$purifier = CheckHtml::purify();
		$errors   = array();

		$body = str_replace(
			array(
				'{%EMAIL%}',
				'{%CODE%}',
				'{%AMOUNT%}',
				'{%START-DATE%}',
				'{%END-DATE%}',
				'{%MIN-TICKETS%}',
				'{%MAX-TICKETS%}',
				'{%MIN-AMOUNT%}',
				'{%MAX-AMOUNT%}',
			),
			array(
				$request['email'],
				'CODE-DISCOUNT-24',
				'20.00',
				wp_date( 'Y-m-d' ) . ' 00:00:00',
				wp_date( 'Y-m-d', TimeUtil::local_time() + ( 24 * 3600 * 14 ) ) . ' 14:00:00',
				'4',
				'10',
				'25.00',
				'100.00',
			),
			urldecode( $request['body'] )
		);

		// Fake a result.
		$result                 = new stdClass();
		$result->id             = '0';
		$result->event_id       = '0';
		$result->uid            = 'R4FETmO6RJtFJ1hysKikMiZLM2DGHC9C3ONSvXUt';
		$result->sender_name    = '';
		$result->sender_email   = '';
		$result->payment_status = '';
		$result->name           = 'Sara Doe';
		$result->email          = sanitize_email( $request['email'] );
		$result->created_at     = wp_date( 'Y-m-d H:i:s' );
		$result->email_subject  = sanitize_text_field( $request['subject'] );
		$result->email_body     = $purifier->purify( $body );
		$result->email_bcc      = '';
		$result->redirect       = '';
		$result->input_fields   = '';

		// Save the message.
		$msg_id = $this->options->save_message( $result );

		// Send the email.
		try {
			$this->mailer->send_email( $result, $msg_id );
		} catch ( Exception $e ) {
			$errors[] = array(
				'id'    => 4376,
				'error' => $e->getMessage(),
			);
		}

		return rest_ensure_response( array( 'errors' => $errors ) );
	}


	/**
	 * Send emails to closed user groups
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_Error|array
	 *
	 * @since 2.2.0
	 */
	private function send_closed_user_group_emails( WP_REST_Request $request ): WP_Error|array {
		global $wpdb;

		// Is the template code available?
		if ( empty( $request['template_code'] ) ) {
			return new WP_Error( 'no_template', __( 'No coupon template provided', 'fast-events' ), array( 'status' => 400 ) );
		}
		$template = $wpdb->get_row( 'SELECT * FROM ' . $wpdb->prefix . 'fe_event_coupons WHERE code="' . $request['template_code'] . '"' ); // phpcs:ignore
		if ( empty( $template ) ) {
			return new WP_Error( 'not_found', __( 'Coupon template not found', 'fast-events' ), array( 'status' => 400 ) );
		}

		$ids = $wpdb->get_results(
			'SELECT * FROM ' . $wpdb->prefix . 'fe_event_user_groups WHERE id IN(' .
			implode( ',', array_map( 'absint', $request['ids'] ) ) . ') ' . // phpcs:ignore
			$this->auth->get_restricted_events( $this->auth::FAST_EVENTS_AUTH_QUERY_ORDER_LOOKUP ) // phpcs:ignore
		);
		// Boot the HTML Purifier.
		$purifier = CheckHtml::purify();

		// Loop through the batch.
		$errors = array();
		foreach ( $ids as $id ) {
			$body = str_replace(
				array(
					'{%EMAIL%}',
					'{%CODE%}',
					'{%AMOUNT%}',
					'{%START-DATE%}',
					'{%END-DATE%}',
					'{%MIN-TICKETS%}',
					'{%MAX-TICKETS%}',
					'{%MIN-AMOUNT%}',
					'{%MAX-AMOUNT%}',
				),
				array(
					sanitize_email( $id->email ),
					$template->code,
					number_format_i18n( (float) $template->amount, 2 ),
					$template->start_date,
					$template->end_date,
					$template->minimum_tickets,
					$template->maximum_tickets,
					number_format_i18n( (float) $template->minimum_amount, 2 ),
					number_format_i18n( (float) $template->maximum_amount, 2 ),
				),
				urldecode( $request['body'] )
			);

			$result                 = new stdClass();
			$result->id             = '0';
			$result->event_id       = $id->event_id;
			$result->uid            = 'NOT-USED';
			$result->sender_name    = '';
			$result->sender_email   = '';
			$result->payment_status = '';
			$result->name           = $id->name;
			$result->email          = sanitize_email( $id->email );
			$result->created_at     = wp_date( 'Y-m-d H:i:s' );
			$result->email_subject  = $request['subject'];
			$result->email_body     = $purifier->purify( $body );
			$result->email_bcc      = '';
			$result->redirect       = '';
			$result->input_fields   = '';

			// Save the message.
			$msg_id = $this->options->save_message( $result );

			// Send the email.
			try {
				$this->mailer->send_email( $result, $msg_id );
			} catch ( Exception $e ) {
				$errors[] = array(
					'id'    => $id->id,
					'error' => $e->getMessage(),
				);
			}
		}

		return $errors;
	}


	/**
	 * Send emails based on coupons with an emailaddress
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_Error|array
	 *
	 * @since 2.2.0
	 */
	private function send_coupon_emails( WP_REST_Request $request ): WP_Error|array {
		global $wpdb;

		// Get all event ids the user is authorized for.
		$auth_query = $this->auth->get_restricted_events( $this->auth::FAST_EVENTS_AUTH_QUERY_EVENTS );
		$event_ids  = $wpdb->get_col(
			'SELECT id FROM ' . $wpdb->prefix . 'fe_events ' .
			( empty( $auth_query ) ? 'WHERE event_type != 0' : ( $auth_query . ' AND event_type != 0' ) ) // phpcs:ignore
		);

		$ids = $wpdb->get_results(
			'SELECT id, code, amount, start_date, end_date, events, minimum_tickets, maximum_tickets, ' .
			'minimum_amount, maximum_amount, email FROM ' . $wpdb->prefix . 'fe_event_coupons WHERE id IN(' .
			implode( ',', array_map( 'absint', $request['ids'] ) ) . ')' // phpcs:ignore
		);
		// Boot the HTML Purifier.
		$purifier = CheckHtml::purify();

		// Loop through the batch.
		$errors = array();
		foreach ( $ids as $id ) {

			// Is the emailaddress available?
			$email = $id->email;
			if ( ! empty( $request['email'] ) ) {
				$email = $request['email']; // Used by Admin App to send a single coupon to the user.
			} elseif ( empty( $id->email ) ) {
				$errors[] = array(
					'id'    => $id->id,
					'error' => __( 'No email address available', 'fast-events' ),
				);
				continue;
			}

			// Is the coupon limited to certain events, and are we allowed access to these events?
			if ( ! empty( $id->events ) && empty( array_intersect( $event_ids, explode( ',', $id->events ) ) ) ) {
				$errors[] = array(
					'id'    => $id->id,
					'error' => __( 'Not authorised for events: ', 'fast-events' ) . $id->events,
				);
				continue;
			}

			$body = str_replace(
				array(
					'{%EMAIL%}',
					'{%CODE%}',
					'{%AMOUNT%}',
					'{%START-DATE%}',
					'{%END-DATE%}',
					'{%MIN-TICKETS%}',
					'{%MAX-TICKETS%}',
					'{%MIN-AMOUNT%}',
					'{%MAX-AMOUNT%}',
				),
				array(
					sanitize_email( $id->email ),
					$id->code,
					number_format_i18n( (float) $id->amount, 2 ),
					$id->start_date,
					$id->end_date,
					$id->minimum_tickets,
					$id->maximum_tickets,
					number_format_i18n( (float) $id->minimum_amount, 2 ),
					number_format_i18n( (float) $id->maximum_amount, 2 ),
				),
				urldecode( $request['body'] )
			);

			$result                 = new stdClass();
			$result->id             = '0';
			$result->event_id       = '0';
			$result->uid            = 'NOT-USED';
			$result->sender_name    = '';
			$result->sender_email   = '';
			$result->payment_status = '';
			$result->name           = '';
			$result->email          = sanitize_email( $email );
			$result->created_at     = wp_date( 'Y-m-d H:i:s' );
			$result->email_subject  = $request['subject'];
			$result->email_body     = $purifier->purify( $body );
			$result->email_bcc      = '';
			$result->redirect       = '';
			$result->input_fields   = '';

			// Save the message.
			$msg_id = $this->options->save_message( $result );

			// Send the email.
			try {
				$this->mailer->send_email( $result, $msg_id );
			} catch ( Exception $e ) {
				$errors[] = array(
					'id'    => $id->id,
					'error' => $e->getMessage(),
				);
			}
		}

		return $errors;
	}


	/**
	 * Filter a list of coupons
	 *
	 * @param WP_REST_Request $request Request object.
	 * @param array           $items   Array of coupons.
	 * @return array Array of coupon ids
	 *
	 * @since 2.2.0
	 */
	private function filter_coupons( WP_REST_Request $request, array $items ): array {
		global $wpdb;

		$format    = 'Y-m-d H:i:s';
		$ids       = array();
		$prefix    = $request['code_prefix'];
		$suffix    = $request['code_suffix'];
		$date_from = DateTime::createFromFormat( $format, $request['date_from'] );
		$date_to   = DateTime::createFromFormat( $format, $request['date_to'] );
		$min_tick  = $request['tickets_minimum'];
		$max_tick  = $request['tickets_maximum'];
		$min_amt   = (float) $request['amount_minimum'];
		$max_amt   = (float) $request['amount_maximum'];

		// Get all event ids the user is authorized for.
		$auth_query = $this->auth->get_restricted_events( $this->auth::FAST_EVENTS_AUTH_QUERY_EVENTS );
		$event_ids  = $wpdb->get_col(
			'SELECT id FROM ' . $wpdb->prefix . 'fe_events ' .
			( empty( $auth_query ) ? 'WHERE event_type != 0' : ( $auth_query . ' AND event_type != 0' ) ) // phpcs:ignore
		);
		if ( ! empty( $request['event_ids'] ) ) {
			$event_ids = array_intersect( $event_ids, explode( ',', $request['event_ids'] ) );
		}

		foreach ( $items as $item ) {
			$df = DateTime::createFromFormat( $format, $item->start_date );
			$dt = DateTime::createFromFormat( $format, $item->end_date );
			if (
				( is_email( $item->email ) ) &&
				( empty( $prefix ) || str_starts_with( $item->code, $prefix ) ) &&
				( empty( $suffix ) || str_ends_with( $item->code, $suffix ) ) &&
				( $df <= $date_from ) &&
				( $dt >= $date_to ) &&
				( empty( $item->minimum_tickets ) || (int) $item->minimum_tickets >= $min_tick ) &&
				( empty( $item->maximum_tickets ) || (int) $item->maximum_tickets <= $max_tick ) &&
				( empty( $item->minimum_amount ) || (float) $item->minimum_amount >= $min_amt ) &&
				( empty( $item->maximum_amount ) || (float) $item->maximum_amount <= $max_amt ) &&
				( empty( $item->events ) || ! empty( array_intersect( $event_ids, explode( ',', $item->events ) ) ) )
			) {
				$ids[] = $item->id;
			}
		}

		return $ids;
	}


	/**
	 * Generate a list of events
	 * Create part of a query to check for the right events
	 *
	 * @param ?string $param Comma separated list of event ids.
	 * @return string
	 *
	 * @since 2.2.0
	 */
	private function fast_events_tools_check_events( ?string $param ): string {
		$event_ids = array_map( 'absint', $this->auth->get_authorized_event_ids() );
		if ( ! empty( $param ) ) {
			$ids = array_map( 'absint', explode( ',', $param ) );

			// Check if the ids are authorized.
			if ( ! empty( $event_ids ) ) {
				foreach ( $ids as $id ) {
					if ( ! in_array( $id, $event_ids, true ) ) {
						return 'WHERE event_id IN (' . implode( ',', $event_ids ) . ')';
					}
				}
			}

			return 'WHERE event_id IN (' . implode( ',', $ids ) . ')';
		} elseif ( ! empty( $event_ids ) ) {
			return 'WHERE event_id IN (' . implode( ',', $event_ids ) . ')';
		}

		return '';
	}


	/**
	 * Prepare the output for response.
	 *
	 * @param mixed           $item    Array of order_ids.
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response Response object.
	 *
	 * @since 2.2.0
	 */
	public function prepare_item_for_response( $item, $request ): WP_REST_Response {

		$data   = array();
		$fields = $this->get_fields_for_response( $request );

		if ( rest_is_field_included( 'bulk_source', $fields ) ) {
			$data['bulk_source'] = $request['bulk_source'];
		}

		if ( rest_is_field_included( 'event_ids', $fields ) ) {
			$data['event_ids'] = $request['event_ids'];
		}

		if ( rest_is_field_included( 'template_code', $fields ) ) {
			$data['template_code'] = $request['template_code'];
		}

		if ( rest_is_field_included( 'code_prefix', $fields ) ) {
			$data['code_prefix'] = $request['code_prefix'];
		}

		if ( rest_is_field_included( 'code_suffix', $fields ) ) {
			$data['code_suffix'] = $request['code_suffix'];
		}

		if ( rest_is_field_included( 'date_from', $fields ) ) {
			$data['date_from'] = $request['date_from'];
		}

		if ( rest_is_field_included( 'date_to', $fields ) ) {
			$data['date_to'] = $request['date_to'];
		}

		if ( rest_is_field_included( 'tickets_minimum', $fields ) ) {
			$data['tickets_minimum'] = $request['tickets_minimum'];
		}

		if ( rest_is_field_included( 'tickets_maximum', $fields ) ) {
			$data['tickets_maximum'] = $request['tickets_maximum'];
		}

		if ( rest_is_field_included( 'amount_minimum', $fields ) ) {
			$data['amount_minimum'] = $request['amount_minimum'];
		}

		if ( rest_is_field_included( 'amount_maximum', $fields ) ) {
			$data['amount_maximum'] = $request['amount_maximum'];
		}

		if ( rest_is_field_included( 'batch_size', $fields ) ) {
			$data['batch_size'] = $this->batch_size;
		}

		if ( rest_is_field_included( 'ids', $fields ) ) {
			$data['ids'] = array_map( 'absint', $item );
		}

		$context = ! empty( $request['context'] ) ? $request['context'] : 'embed';

		$data = $this->add_additional_fields_to_object( $data, $request );
		$data = $this->filter_response_by_context( $data, $context );

		// Wrap the data in a response object.
		return rest_ensure_response( $data );
	}


	/**
	 * Return the coupons bulk emails schema.
	 *
	 * @return array
	 *
	 * @since 2.2.0
	 */
	public function get_item_schema(): array {
		if ( $this->schema ) {
			return $this->add_additional_fields_schema( $this->schema );
		}

		$this->schema = array(
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
			'title'      => 'coupons-bulk-emails',
			'type'       => 'object',
			'properties' => array(
				'bulk_source'     => array(
					'description' => __( 'Source (coupons or user groups) for the coupon bulk emails.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'string',
					'enum'        => array( '0', '1' ),
				),
				'event_ids'       => array(
					'description' => __( 'Comma separated list of event ids.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'string',
					'maxLength'   => 256,
					'pattern'     => '^\d*(,\d+)*$',
				),
				'template_code'   => array(
					'description' => __( 'The coupon code used as template if the source is user groups.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'string',
					'maxLength'   => 32,
				),
				'code_prefix'     => array(
					'description' => __( 'Coupon code prefix text.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'string',
					'maxLength'   => 8,
				),
				'code_suffix'     => array(
					'description' => __( 'Coupon code suffix text.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'string',
					'maxLength'   => 8,
				),
				'date_from'       => array(
					'description' => __( 'Coupon code is valid from this date.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'string',
					'format'      => 'date-time',
				),
				'date_to'         => array(
					'description' => __( 'Coupon code is valid until this date.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'string',
					'format'      => 'date-time',
				),
				'tickets_minimum' => array(
					'description' => __( 'Minimum number of tickets required for coupon.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'integer',
					'arg_options' => array(
						'sanitize_callback' => 'absint',
					),
				),
				'tickets_maximum' => array(
					'description' => __( 'Maximum number of tickets allowed for coupon.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'integer',
					'arg_options' => array(
						'sanitize_callback' => 'absint',
					),
				),
				'amount_minimum'  => array(
					'description' => __( 'Minimum amount required for coupon.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'number',
				),
				'amount_maximum'  => array(
					'description' => __( 'Maximum amount allowed for coupon.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'number',
				),
				'email'           => array(
					'description' => __( 'The emailaddress of the user.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'type'        => 'string',
					'format'      => 'email',
					'maxLength'   => 100,
				),
				'subject'         => array(
					'description' => __( 'The subject of the email.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'string',
					'maxLength'   => 100,
				),
				'body'            => array(
					'description' => __( 'The body of the email.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'required'    => true,
					'type'        => 'string',
					'maxLength'   => 1000000,
				),
				'batch_size'      => array(
					'description' => __( 'Maximum size of the request buffer with ids.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'readonly'    => true,
					'type'        => 'integer',
				),
				'ids'             => array(
					'description' => __( 'Array of coupon ids or event ids.', 'fast-events' ),
					'context'     => array( 'view', 'edit', 'embed' ),
					'type'        => 'array',
					'uniqueItems' => true,
					'items'       => array(
						'type' => 'integer',
					),
				),
			),
		);

		return $this->add_additional_fields_schema( $this->schema );
	}
}
