<?php
/**
 * Tickets download controller.
 *
 * @package Fast-Events/Rest-API/Downloads
 * @since 1.0
 */

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

defined( 'ABSPATH' ) || exit;

use FeData\FastEvents\Helpers\PersonalisationHelper;
use FeData\FastEvents\Storage\PluginSettings;
use FeData\FastEvents\Utilities\PluginUtil;
use FeData\FastEvents\Utilities\WebhookUtil;
use JetBrains\PhpStorm\NoReturn;
use WP_REST_Request;
use WP_REST_Server;

/**
 * Downloads class.
 */
class TicketsDownloadController {


	/**
	 * Tickets download constructor.
	 *
	 * @since 1.0
	 *
	 * @param PluginSettings        $settings        Plugin settings.
	 * @param PersonalisationHelper $personalisation Personalisation helper.
	 */
	public function __construct(
		private readonly PluginSettings $settings,
		private readonly PersonalisationHelper $personalisation
	) {}


	/**
	 * Register the routes for the download of the tickets.
	 *
	 * @since 1.0
	 * @since 2.1.0 Added download tickets via qrcode ids (1 or more)
	 */
	public function register_routes(): void {

		// Download all tickets via uid.
		register_rest_route(
			'fast-events',
			'/v1/tickets/(?P<uid>[\w]{40})',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'fast_events_download_tickets' ),
				'permission_callback' => '__return_true',
			)
		);

		// Download tickets for give qrcode_ids.
		register_rest_route(
			'fast-events',
			'/v1/tickets/(?P<ids>\d+(?:-\d+)*)/(?P<hash>[a-f0-9]{40})',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'fast_events_download_qrcode_ids' ),
				'permission_callback' => '__return_true',
			)
		);
	}


	/**
	 * Get all tickets via the order uid.
	 *
	 * @param WP_REST_Request $data Request instance.
	 *
	 * @since 2.1.0 Added personalised input
	 *
	 * @since 1.0
	 */
	#[NoReturn]
	public function fast_events_download_tickets( WP_REST_Request $data ): void {
		global $wpdb;

		// Get all the qrcodes.
		$etable = $wpdb->prefix . 'fe_events';
		$otable = $wpdb->prefix . 'fe_event_orders';
		$qtable = $wpdb->prefix . 'fe_event_qrcodes';
		// phpcs:disable
		$result = $wpdb->get_results(
			"SELECT $otable.id, $otable.name, $otable.email, $otable.payment_status, $otable.input_fields as order_input, " .
			"$etable.event_name, $etable.event_date, $etable.event_date_format, $etable.tickets_needed, $etable.seats_needed, " .
			"$etable.webhooks_needed, $etable.tracking_needed, $etable.pdf_info, $etable.input_fields as event_input, " .
			"$qtable.id as qrcode_id, $qtable.qrcode, $qtable.ticket_type, $qtable.event_id, $qtable.personalised_input " .
			"FROM $qtable " .
			"INNER JOIN $otable ON $otable.id = $qtable.order_id " .
			"INNER JOIN $etable ON $etable.id = $qtable.event_id " .
			"WHERE $qtable.order_id = (SELECT id FROM $otable WHERE uid = '" . $data['uid'] . "')"
		);
		// phpcs:enable

		$this->download_tickets( $result );
	}


	/**
	 * Get all tickets via the order uid.
	 *
	 * @param WP_REST_Request $data Request instance.
	 *
	 * @since 2.1.0 Added personalised input
	 *
	 * @since 1.0
	 */
	#[NoReturn]
	public function fast_events_download_qrcode_ids( WP_REST_Request $data ): void {
		global $wpdb;

		// Does the hash match?
		if ( ! $this->personalisation->validate_download_hash( $data['ids'], $data['hash'] ) ) {
			http_response_code( 404 );
			die();
		}

		// Get all the qrcodes for these qrcode_ids.
		$etable = $wpdb->prefix . 'fe_events';
		$otable = $wpdb->prefix . 'fe_event_orders';
		$qtable = $wpdb->prefix . 'fe_event_qrcodes';
		// phpcs:disable
		$result = $wpdb->get_results(
			"SELECT $otable.id, $otable.name, $otable.email, $otable.payment_status, $otable.input_fields as order_input, " .
			"$etable.event_name, $etable.event_date, $etable.event_date_format, $etable.tickets_needed, $etable.seats_needed, " .
			"$etable.webhooks_needed, $etable.tracking_needed, $etable.pdf_info, $etable.input_fields as event_input, " .
			"$qtable.id as qrcode_id, $qtable.qrcode, $qtable.ticket_type, $qtable.event_id, $qtable.personalised_input " .
			"FROM $qtable " .
			"INNER JOIN $otable ON $otable.id = $qtable.order_id " .
			"INNER JOIN $etable ON $etable.id = $qtable.event_id " .
			"WHERE $qtable.id IN (" . str_replace( '-', ',', $data['ids'] ) . ')'
		);
		// phpcs:enable

		$this->download_tickets( $result );
	}


	/**
	 * Generate and download tickets
	 *
	 * @param mixed $result Query result.
	 *
	 * @since 2.1.0
	 */
	#[NoReturn]
	private function download_tickets( mixed $result ): void {
		if ( empty( $result ) ) {
			http_response_code( 404 );
			die();
		}

		// Do the events support tickets?
		if ( 0 === (int) $result[0]->tickets_needed ) {
			http_response_code( 404 );
			die();
		}

		// Check for personalisation.
		list( $personalise, $layout ) = $this->personalisation->get_ticket_info( $result[0]->event_input );
		foreach ( $result as $ticket ) {
			if ( empty( $personalise[ $ticket->ticket_type ] ) ) {
				continue; // No personalised fields for this ticket.
			}
			if ( empty( $ticket->personalised_input ) ) {
				http_response_code( 400 );
				die(); // This should not happen, there has to be personalised input.
			}
			$info = json_decode( $ticket->personalised_input );
			if ( null !== $info && false !== $info ) {
				if ( ! isset( $info->locked ) || false === $info->locked ) {
					http_response_code( 400 );
					die(); // The personalised input is not locked.
				}
				continue; // Personalised input is locked -> OK.
			}
			http_response_code( 400 );
			die(); // No personalised input found.
		}

		// Prepare the PDF.
		$pdf = new EventTickets( $this->settings->sender_name(), $result[0]->pdf_info, $layout );

		// Create the Qrcode pages.
		$pdf->print_qrcodes( $result );

		// Send the PDF to the client.
		$pdf->send_pdf();

		// Are webhooks activated for this event?

		if ( 1 === (int) $result[0]->webhooks_needed ) {
			WebhookUtil::create_webhook( 'tickets.downloaded', array( (int) $result[0]->id, current_time( 'mysql' ), PluginUtil::get_ip() ) );
		}

		die();
	}
}
