<?php
/**
 * A class to deliver event-related topics to a webhook.
 *
 * @since 3.0.0
 */

declare( strict_types=1 );
namespace FeData\FastEvents\Hooks\Webhooks\Topic;

use FeData\FastEvents\Helpers\SeatsHelper;
use FeData\FastEvents\Hooks\Webhooks\AbstractWebhook;
use stdClass;

defined( 'ABSPATH' ) || exit;


/**
 * A class to deliver event-related topics to a webhook.
 */
final class EventTopic extends AbstractWebhook {

	/**
	 * Dispatch 'event.created', 'event.updated', 'event.deleted'.
	 *
	 * @since 3.0.0
	 *
	 * @param string   $dispatch Subtopic to dispatch ('created', 'updated', 'deleted').
	 * @param stdClass $webhook  Detailed information on the webhook.
	 * @param mixed    $arg      Event identifier (int).
	 */
	public function dispatch( string $dispatch, stdClass $webhook, mixed $arg ): void {
		$this->{$dispatch . '_event'}( $webhook, $arg );
	}


	/**
	 * Webhook for adding a new event.
	 *
	 * @since 1.0
	 * @since 2.3.0 Use fast_events_json_encode.
	 *
	 * @param stdClass $webhook     Detailed information on the webhook.
	 * @param int      $event_id    Event identifier.
	 */
	private function created_event( stdClass $webhook, int $event_id ): void {

		$this->webhook = $webhook;

		$event = $this->get_event_info( $event_id );
		if ( isset( $event['webhook-id'] ) ) {
			$this->logger->error( 'Webhook error', $event );
			return;
		}

		$this->deliver( $event );
	}


	/**
	 * Webhook for updating an event.
	 *
	 * @since 1.0
	 * @since 2.3.0 Use fast_events_json_encode.
	 *
	 * @param stdClass $webhook     Detailed information on the webhook.
	 * @param int      $event_id    Event identifier.
	 */
	private function updated_event( stdClass $webhook, int $event_id ): void {

		$this->webhook = $webhook;

		$event = $this->get_event_info( $event_id );
		if ( isset( $event['webhook-id'] ) ) {
			$this->logger->error( 'Webhook error', $event );
			return;
		}

		$this->deliver( $event );
	}


	/**
	 * Webhook for deleting an event.
	 *
	 * @since 1.0
	 *
	 * @param stdClass $webhook     Detailed information on the webhook.
	 * @param int      $event_id    Event identifier.
	 */
	private function deleted_event( stdClass $webhook, int $event_id ): void {

		$this->webhook = $webhook;

		$this->deliver( array( 'id' => $event_id ) );
	}


	/**
	 * Event lookup.
	 *
	 * @since 1.0
	 * @since 1.4.0 Added saas_fee, saas_user_id, sender_name and sender_email to result
	 * @since 2.2.0 Added 'no_border', 'coupons_needed', 'min', 'max' and 'personalise'
	 *
	 * @param int $event_id    Event identifier.
	 *
	 * @return array
	 */
	private function get_event_info( int $event_id ): array {
		global $wpdb;
		global $fevt_container;

		// Get seats configuration.
		$seats_func   = $fevt_container->get( SeatsHelper::class );
		$seats_config = array();
		$seats        = $seats_func->get_entry_for_event( $event_id );
		if ( is_wp_error( $seats ) ) {
			return array(
				'type'       => 'Webhook',
				'webhook-id' => (int) $this->webhook->id,
				'name'       => $this->webhook->name,
				'url'        => $this->webhook->url,
				'topic'      => $this->webhook->topic,
				'error'      => $seats_func->get_error_message(),
			);
		}
		$seats_config['number']       = (int) $seats->num_seats;
		$seats_config['format']       = $seats->seat_format;
		$seats_config['config']       = $seats->seat_config;
		$seats_config['linked_event'] = (int) $seats->linked_event;

		$event = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}fe_events WHERE id=%d", $event_id ) );
		if ( null === $event ) {
			$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}fe_event_webhooks SET pending=GREATEST(0, pending-1) WHERE id = %d", (int) $this->webhook->id ) );
			return array(
				'type'       => 'Webhook',
				'webhook-id' => (int) $this->webhook->id,
				'name'       => $this->webhook->name,
				'url'        => $this->webhook->url,
				'topic'      => $this->webhook->topic,
				'error'      => '** Event #' . $event_id . ' not found **',
			);
		}

		// Set extra input fields and ticket fields.
		$submit  = '';
		$extra   = array();
		$tickets = array();
		$group   = array();
		$uniq    = '';
		$input   = json_decode( $event->input_fields );
		if ( null !== $input ) {
			$submit = $input->submit->name;
			$uniq   = $input->unique_users->master_eventids;

			// Extra input fields.
			$tmp = array();
			foreach ( $input->fields as $field ) {
				$tmp['id']          = $field->id;
				$tmp['name']        = $field->name;
				$tmp['type']        = $field->type;
				$tmp['value']       = $field->value;
				$tmp['min']         = $field->min;
				$tmp['max']         = $field->max;
				$tmp['personalise'] = 1 === $field->personalise;
				$tmp['is_required'] = 1 === $field->required;
				$extra []           = $tmp;
			}

			// Ticket fields.
			foreach ( $input->tickets as $ticket ) {
				$tmp          = array();
				$tmp['id']    = $ticket->id;
				$tmp['name']  = $ticket->name;
				$tmp['price'] = (float) $ticket->price;
				$tmp['vat']   = (float) $ticket->vat;
				if ( '' === $ticket->stock ) {
					$tmp['stock_control'] = false;
				} else {
					$tmp['stock_control'] = true;
					$tmp['stock']         = (int) $ticket->stock;
				}
				$tmp['minimum_to_order'] = (int) $ticket->min;
				$tmp['maximum_to_order'] = (int) $ticket->max;
				$tmp['is_counted']       = 1 === $ticket->cnt;
				$tickets[]               = $tmp;
			}

			// User group info.
			$group_type          = (int) $input->user_group->id;
			$group['group_type'] = $group_type;
			if ( 1 === $group_type ) {
				$group['wordpress_roles'] = '' !== $input->user_group->roles ? explode( ',', $input->user_group->roles ) : array();
			} elseif ( 2 === $group_type ) {
				if ( '' !== $input->user_group->eventid ) {
					$group['event_id'] = (int) $input->user_group->eventid;
				}
			} elseif ( 3 === $group_type ) {
				$group['rest_header'] = $input->user_group->rest_header;
				$group['rest_url']    = $input->user_group->rest_url;
			}
		}

		// Set scan fields.
		$scans     = array();
		$scan_info = json_decode( $event->scan_keys );
		if ( null !== $scan_info ) {
			$tmp = array();
			foreach ( $scan_info as $key => $value ) {
				$tmp['key']         = $key;
				$tmp['level']       = (int) $value->entry;
				$tmp['tickets']     = '' !== $value->tickets ? explode( ',', $value->tickets ) : array();
				$tmp['location']    = $value->location;
				$tmp['date_format'] = $value->date_format;
				$scans[]            = $tmp;
			}
		}

		// Set pdf fields.
		$pdf      = array();
		$pdf_info = json_decode( $event->pdf_info );
		if ( null !== $pdf_info ) {

			// Add the attachment_id to the tickets input_field.
			foreach ( $pdf_info->ticket->types as $key => $value ) {
				$el = array_search( $key, array_column( $tickets, 'name' ), true );
				if ( false !== $el ) {
					$tickets[ $el ]['attachment_id'] = (int) $value;
				}
			}

			$pdf = array(
				'ticket'  => array(
					'attachment_id' => (int) $pdf_info->ticket->id,
					'x_position'    => (int) $pdf_info->ticket->x,
					'y_position'    => (int) $pdf_info->ticket->y,
					'rotation'      => (int) $pdf_info->ticket->rotate,
					'scale'         => isset( $pdf_info->ticket->scale ) ? (int) $pdf_info->ticket->scale : 100,
					'no_border'     => 1 === $pdf_info->ticket->no_border,
				),
				'invoice' => array(
					'attachment_id'           => (int) $pdf_info->invoice->id,
					'use_vat'                 => 1 === (int) $pdf_info->invoice->vat,
					'name_position'           => array(
						'x_position' => (int) $pdf_info->invoice->name->x,
						'y_position' => (int) $pdf_info->invoice->name->y,
					),
					'invoice_number_position' => array(
						'x_position' => (int) $pdf_info->invoice->invoiceno->x,
						'y_position' => (int) $pdf_info->invoice->invoiceno->y,
					),
					'first_line_position'     => array(
						'x_position' => (int) $pdf_info->invoice->line->x,
						'y_position' => (int) $pdf_info->invoice->line->y,
						'line_width' => (int) $pdf_info->invoice->line->w,
					),
				),
			);
		}

		// Tracking info.
		$tracking      = array();
		$tracking_info = json_decode( $event->tracking_info );
		if ( null !== $tracking_info ) {
			$tracking = array(
				'start_tracking'     => $tracking_info->start_tracking,
				'stop_tracking'      => $tracking_info->stop_tracking,
				'geofence_radius'    => $tracking_info->geofence_radius ?? 200,
				'distance_filter'    => $tracking_info->distance_filter ?? 10,
				'no_entry_scan'      => $tracking_info->no_entry_scan ?? false,
				'force_tracking_app' => $tracking_info->force_tracking_app ?? false,
				'tr_help_url'        => $tracking_info->tr_help_url ?? home_url(),
				'tr_help_tel'        => $tracking_info->tr_help_tel ?? '',
			);
		}

		return array(
			'id'                          => $event_id,
			'event_name'                  => $event->event_name,
			'event_date'                  => $event->event_date,
			'event_date_format'           => $event->event_date_format,
			'start_date'                  => $event->start_date,
			'end_date'                    => $event->end_date,
			'event_type'                  => (int) $event->event_type,
			'stock'                       => (int) $event->stock,
			'stock_link'                  => (int) $event->stock_link,
			'saas_fee'                    => is_null( $event->saas_fee ) ? '' : (float) $event->saas_fee,
			'saas_user_id'                => (float) $event->saas_user_id,
			'group_type'                  => (int) $event->group_type,
			'event_group'                 => $event->event_group,
			'redirect'                    => $event->redirect,
			'email'                       => array(
				'sender_name'  => $event->sender_name,
				'sender_email' => $event->sender_email,
				'bcc'          => $event->email_bcc,
				'subject'      => $event->email_subject,
				'body'         => $event->email_body,
			),
			'email_confirmation'          => array(
				'bcc'      => $event->confirm_bcc,
				'subject'  => $event->confirm_subject,
				'body'     => $event->confirm_body,
				'redirect' => $event->confirm_redirect,
			),
			'emails_needed'               => 1 === (int) $event->emails_needed,
			'tickets_needed'              => 1 === (int) $event->tickets_needed,
			'invoice_needed'              => 1 === (int) $event->invoice_needed,
			'unique_users_needed'         => 1 === (int) $event->unique_users_needed,
			'unique_event_ids'            => $uniq,
			'user_groups_needed'          => 1 === (int) $event->user_groups_needed,
			'recaptcha_needed'            => 1 === (int) $event->recaptcha_needed,
			'confirmation_emails_needed'  => 1 === (int) $event->confirmation_emails_needed,
			'confirmation_timeout'        => (int) $event->confirmation_timeout,
			'add_dashboard_orders_needed' => 1 === (int) $event->add_dashboard_orders_needed,
			'test_payments_needed'        => 1 === (int) $event->test_payments_needed,
			'seats_needed'                => 1 === (int) $event->seats_needed,
			'webhooks_needed'             => 1 === (int) $event->webhooks_needed,
			'reload_on_exit_needed'       => 1 === (int) $event->reload_on_exit_needed,
			'tracking_needed'             => 1 === (int) $event->tracking_needed,
			'coupons_needed'              => 1 === (int) $event->coupons_needed,
			'terms'                       => $event->terms,
			'pdf_fields'                  => $pdf,
			'scan_keys'                   => $scans,
			'order_submit_text'           => $submit,
			'input_fields'                => $extra,
			'ticket_types'                => $tickets,
			'user_groups'                 => $group,
			'seats'                       => $seats_config,
			'tracking'                    => $tracking,
		);
	}
}
