<?php
/**
 * Free-tier onboarding wizard and setup checklist (RTEC-inspired; see docs/onboarding-wizard-and-setup-checklist-plan.md).
 *
 * @package WPEventGenius
 */

namespace WPEventGenius\Admin\Services;

use WPEventGenius\Admin\CustomPostTypes\QuickCreate\EventCreate;
use WPEventGenius\Admin\Page\AllEvents\EventSinglePage;
use WPEventGenius\Common\Utils\Defaults;
use WPEventGenius\Common\Utils\Formatter;
use WPEventGenius\Common\Utils\Settings;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Onboarding wizard + checklist state for Event Genius (free).
 */
class EvgeOnboardingService {

	const PAGE_SLUG = 'evge-onboarding';

	const OPTION_NAME = 'evge_onboarding_state';

	const META_FINISH_SETUP = '_evge_finish_setup_pending';

	const TRANSIENT_REDIRECT = 'evge_activation_redirect';

	const TRANSIENT_SUCCESS_URL = 'evge_onboarding_success_event_url';

	const TRANSIENT_SUCCESS_EVENT_ID = 'evge_onboarding_success_event_id';

	/**
	 * Query arg appended to the post-registration admin link when that submission was the site's first registration.
	 */
	const QUERY_FIRST_REGISTRATION_ADMIN_SUCCESS = 'evge_first_registration_success';

	const KEY_WIZARD_COMPLETED    = 'wizard_completed';

	const KEY_CHECKLIST_INITIATED = 'checklist_initiated';

	const KEY_CHECKLIST_DISMISSED = 'checklist_dismissed';

	const KEY_FORM_FIELDS_DONE    = 'form_fields_done';

	const KEY_EMAIL_DONE = 'email_done';

	const KEY_EVENT_ARCHIVE_VISIT_DONE = 'event_archive_visit_done';

	/** @var self|null */
	private static $instance;

	/**
	 * Singleton.
	 */
	public static function instance() {
		if ( ! isset( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * @return array<string, bool>
	 */
	public static function get_default_state() {
		return array(
			self::KEY_WIZARD_COMPLETED    => false,
			self::KEY_CHECKLIST_INITIATED => false,
			self::KEY_CHECKLIST_DISMISSED => false,
			self::KEY_FORM_FIELDS_DONE    => false,
			self::KEY_EMAIL_DONE               => false,
			self::KEY_EVENT_ARCHIVE_VISIT_DONE => false,
		);
	}

	/**
	 * @return array<string, bool>
	 */
	public static function get_state() {
		$state = get_option( self::OPTION_NAME, array() );
		if ( ! is_array( $state ) ) {
			$state = array();
		}
		return array_merge( self::get_default_state(), $state );
	}

	/**
	 * @param string $key   self::KEY_* constant.
	 * @param bool   $value Value.
	 */
	public static function set_state_key( $key, $value ) {
		$state         = self::get_state();
		$state[ $key ] = (bool) $value;
		update_option( self::OPTION_NAME, $state );
	}

	/**
	 * Registrations table: db prefix + fixed suffix only (never concatenate user input).
	 *
	 * @global \wpdb $wpdb WordPress database abstraction object.
	 * @return string
	 */
	private static function registrations_table_name() {
		global $wpdb;

		return $wpdb->prefix . 'evge_registrations';
	}

	/**
	 * @global \wpdb $wpdb WordPress database abstraction object.
	 */
	private static function registrations_table_exists() {
		global $wpdb;

		$table = self::registrations_table_name();
		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$found = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) );

		return ( $found === $table );
	}

	/**
	 * Called from ActivationService on each site activation (free only).
	 *
	 * @param bool $has_existing_data When true, skip first-run wizard/checklist nags.
	 */
	public static function on_plugin_activation( $has_existing_data ) {
		delete_transient( self::TRANSIENT_REDIRECT );

		if ( $has_existing_data ) {
			self::set_state_key( self::KEY_WIZARD_COMPLETED, true );
			self::set_state_key( self::KEY_CHECKLIST_INITIATED, false );
			self::set_state_key( self::KEY_CHECKLIST_DISMISSED, true );
			return;
		}

		self::set_state_key( self::KEY_CHECKLIST_INITIATED, true );

		$state = self::get_state();
		if ( empty( $state[ self::KEY_WIZARD_COMPLETED ] ) ) {
			set_transient( self::TRANSIENT_REDIRECT, true, 30 );
		}
	}

	/**
	 * Whether the site already has EG events or registrations (skip forced onboarding).
	 */
	public static function site_has_existing_evge_data() {
		$counts = wp_count_posts( EVGE_EVENT_POST_TYPE );
		if ( $counts ) {
			$total = (int) $counts->publish + (int) $counts->future + (int) $counts->draft + (int) $counts->pending;
			if ( $total > 0 ) {
				return true;
			}
		}

		return false;
	}

	public function init_hooks() {
		if ( ! function_exists( 'evge_is_free_version' ) || ! evge_is_free_version() ) {
			return;
		}

		// After MenusService::add_menus (default 10) so $admin_page_hooks['evge-events'] exists; otherwise
		// add_submenu_page registers the wrong $_registered_pages key and user_can_access_admin_page() fails.
		add_action( 'admin_menu', array( $this, 'register_page' ), 11 );
		add_action( 'admin_page_access_denied', array( $this, 'redirect_completed_onboarding_on_access_denied' ), 1 );
		add_action( 'admin_init', array( $this, 'maybe_exit_onboarding' ), 1 );
		add_action( 'admin_init', array( $this, 'maybe_no_registration_offramp' ), 1 );
		add_action( 'admin_init', array( $this, 'maybe_activation_redirect' ), 2 );
		add_action( 'admin_init', array( $this, 'maybe_redirect_away' ), 5 );
		add_action( 'admin_init', array( $this, 'maybe_dismiss_checklist' ), 5 );
		add_action( 'admin_init', array( $this, 'maybe_checklist_visit_completion' ), 5 );
		add_action( 'admin_init', array( $this, 'set_admin_title_for_removed_onboarding_submenu' ), 999 );

		add_action( 'save_post_' . EVGE_EVENT_POST_TYPE, array( $this, 'clear_finish_setup_flag_on_event_update' ), 20, 3 );

		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_checklist_assets' ) );

		add_action( 'evge_admin_before_main_nav', array( $this, 'render_checklist_placeholder' ) );

		add_action( 'evge_admin_page_inner_start', array( $this, 'render_first_registration_admin_notice' ), 10, 1 );

		add_action( 'wp_ajax_evge_onboarding_create_event', array( $this, 'ajax_create_event' ) );

		add_filter( 'evge_registration_success_response_html', array( $this, 'filter_registration_success_response_html' ), 10, 4 );
	}

	public function register_page() {
		add_submenu_page(
			'evge-events',
			__( 'Setup', 'event-genius' ),
			__( 'Setup', 'event-genius' ),
			'manage_options',
			self::PAGE_SLUG,
			array( $this, 'render_page' )
		);

		// user_can_access_admin_page() runs at the end of menu.php before admin_init. Removing the submenu
		// row breaks get_admin_page_parent() for this slug, so core resolves the wrong hookname and denies
		// access before admin_init — see redirect_completed_onboarding_on_access_denied().
		$state = self::get_state();
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$relaunch = isset( $_GET['relaunch'] ) && (string) wp_unslash( $_GET['relaunch'] ) === '1';
		if ( ! empty( $state[ self::KEY_WIZARD_COMPLETED ] ) && ! $relaunch ) {
			remove_submenu_page( 'evge-events', self::PAGE_SLUG );
		}
	}

	/**
	 * When the submenu row is removed, get_admin_page_title() cannot read a title from $submenu; core then passes null to strip_tags() (PHP 8.1+).
	 */
	public function set_admin_title_for_removed_onboarding_submenu() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( empty( $_GET['page'] ) ) {
			return;
		}
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$page = sanitize_key( wp_unslash( $_GET['page'] ) );
		if ( $page !== self::PAGE_SLUG ) {
			return;
		}

		global $title;
		if ( is_string( $title ) && $title !== '' ) {
			return;
		}

		$title = __( 'Setup', 'event-genius' );
	}

	/**
	 * Free tier: append admin-only note after successful front-end registration (see filter `evge_registration_success_response_html`).
	 *
	 * @param string $response_html        HTML after communicator escaping.
	 * @param string $submission_status    Submission status.
	 * @param int    $event_id             Event post ID.
	 * @param mixed  $registration_group   Registration group object or null.
	 * @return string
	 */
	public function filter_registration_success_response_html( $response_html, $submission_status, $event_id, $registration_group ) {
		if ( ! function_exists( 'evge_is_free_version' ) || ! evge_is_free_version() ) {
			return $response_html;
		}
		if ( 'success' !== $submission_status || $event_id <= 0 ) {
			return $response_html;
		}
		if ( ! is_user_logged_in() || ! current_user_can( 'manage_evge_registrations' ) ) {
			return $response_html;
		}
		$manage_url = add_query_arg(
			array(
				'page'   => 'evge-registrations',
				'tab'    => 'registrations',
				'subtab' => 'single',
				'id'     => absint( $event_id ),
			),
			admin_url( 'admin.php' )
		);
		if ( self::get_registration_count() === 1 ) {
			$manage_url = add_query_arg( self::QUERY_FIRST_REGISTRATION_ADMIN_SUCCESS, '1', $manage_url );
			$manage_url .= '#evge-first-registration-admin-notice';
		}
		$html  = '<div class="evge-registration-success-admin-note">';
		$html .= '<p class="evge-registration-success-admin-note-lead"><strong>' . esc_html__( "You're viewing this as an admin.", 'event-genius' ) . '</strong></p>';
		$html .= '<p class="evge-registration-success-admin-note-text">' . esc_html__( 'Want to manage this registration or view all attendees?', 'event-genius' ) . '</p>';
		$html .= '<p class="evge-registration-success-admin-note-actions"><a class="evge-registration-success-admin-link" href="' . esc_url( $manage_url ) . '">' . esc_html__( 'Manage registrations →', 'event-genius' ) . '</a></p>';
		$html .= '</div>';
		return $response_html . $html;
	}

	/**
	 * First-registration admin deep-link: inline notice at top of event registrations screen.
	 *
	 * @param \WPEventGenius\Admin\Page\BasePage $page Current admin page.
	 */
	public function render_first_registration_admin_notice( $page ) {
		if ( ! $page instanceof EventSinglePage ) {
			return;
		}
		if ( ! self::should_show_first_registration_admin_notice() ) {
			return;
		}
		$message  = '<span style="font-size: 20px; font-weight: bold;">' . esc_html__( '✅ Registration received successfully.', 'event-genius' ) . '</span>';
		$message .= '<br><br>';
		$message .= esc_html__( "You're viewing registrations for this event. Next step: complete your setup using the checklist above.", 'event-genius' );
		$page->inline_generic_notice(
			$message,
			array(
				'id' => 'evge-first-registration-admin-notice',
			)
		);
	}

	/**
	 * Wizard step 3 offramp: disable registration on the new event, dismiss checklist, go to All Events.
	 */
	public function maybe_no_registration_offramp() {
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		if ( ! isset( $_GET['evge_onboarding_no_reg'] ) || '1' !== $_GET['evge_onboarding_no_reg'] ) {
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to do this.', 'event-genius' ) );
		}
		if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'evge_onboarding_no_reg' ) ) {
			wp_safe_redirect( admin_url( 'admin.php?page=' . self::PAGE_SLUG . '&step=3' ) );
			exit;
		}
		$event_id = isset( $_GET['event_id'] ) ? absint( $_GET['event_id'] ) : 0;
		// phpcs:enable WordPress.Security.NonceVerification.Recommended
		if ( ! $event_id || EVGE_EVENT_POST_TYPE !== get_post_type( $event_id ) || ! current_user_can( 'edit_post', $event_id ) ) {
			wp_safe_redirect( admin_url( 'admin.php?page=evge-all-events' ) );
			exit;
		}

		update_post_meta( $event_id, 'evge_allow_registration', 'disabled' );
		self::set_state_key( self::KEY_CHECKLIST_DISMISSED, true );

		wp_safe_redirect( admin_url( 'admin.php?page=evge-all-events' ) );
		exit;
	}

	public function maybe_exit_onboarding() {
		if ( ! isset( $_GET['evge_exit_onboarding'] ) || $_GET['evge_exit_onboarding'] !== '1' ) {
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'evge_exit_onboarding' ) ) {
			return;
		}
		self::set_state_key( self::KEY_WIZARD_COMPLETED, true );
		self::set_state_key( self::KEY_CHECKLIST_INITIATED, true );
		wp_safe_redirect( admin_url( 'admin.php?page=evge-dashboard' ) );
		exit;
	}

	public function maybe_activation_redirect() {
		if ( ! get_transient( self::TRANSIENT_REDIRECT ) ) {
			return;
		}
		if ( isset( $_GET['activate-multi'] ) || is_network_admin() ) {
			delete_transient( self::TRANSIENT_REDIRECT );
			return;
		}
		delete_transient( self::TRANSIENT_REDIRECT );

		$state = self::get_state();
		if ( empty( $state[ self::KEY_WIZARD_COMPLETED ] ) ) {
			wp_safe_redirect( admin_url( 'admin.php?page=' . self::PAGE_SLUG ) );
			exit;
		}

		wp_safe_redirect( admin_url( 'admin.php?page=evge-dashboard' ) );
		exit;
	}

	public function maybe_dismiss_checklist() {
		if ( ! isset( $_GET['evge_dismiss_checklist'] ) || $_GET['evge_dismiss_checklist'] !== '1' ) {
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'evge_dismiss_checklist' ) ) {
			return;
		}
		self::set_state_key( self::KEY_CHECKLIST_DISMISSED, true );
		wp_safe_redirect( remove_query_arg( array( 'evge_dismiss_checklist', '_wpnonce' ) ) );
		exit;
	}

	public function maybe_checklist_visit_completion() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
		$tab  = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : '';
		$sub  = isset( $_GET['subtab'] ) ? sanitize_key( wp_unslash( $_GET['subtab'] ) ) : '';

		if ( $page === 'evge-registrations' && $tab === 'forms' && $sub === 'builder' && isset( $_GET['evge_checklist_visit'] ) && $_GET['evge_checklist_visit'] === 'form' ) {
			self::set_state_key( self::KEY_FORM_FIELDS_DONE, true );
			$form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 1;
			wp_safe_redirect( admin_url( 'admin.php?page=evge-registrations&tab=forms&subtab=builder&form_id=' . $form_id ) );
			exit;
		}

		if ( $page === 'evge-registrations' && $tab === 'forms' && $sub === 'emails' && isset( $_GET['evge_checklist_visit'] ) && $_GET['evge_checklist_visit'] === 'email' ) {
			self::set_state_key( self::KEY_EMAIL_DONE, true );
			$form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 1;
			wp_safe_redirect(
				add_query_arg(
					array(
						'page'          => 'evge-registrations',
						'tab'           => 'forms',
						'subtab'        => 'emails',
						'form_id'       => $form_id,
						'evge_fb_focus' => 'confirmation',
					),
					admin_url( 'admin.php' )
				)
			);
			exit;
		}

		if ( $page === 'evge-settings' && isset( $_GET['evge_checklist_visit'] ) && sanitize_key( wp_unslash( $_GET['evge_checklist_visit'] ) ) === 'archive' ) {
			self::set_state_key( self::KEY_EVENT_ARCHIVE_VISIT_DONE, true );
			$redirect = get_post_type_archive_link( EVGE_EVENT_POST_TYPE );
			if ( ! is_string( $redirect ) || $redirect === '' ) {
				$redirect = home_url( '/' );
			}
			wp_safe_redirect( $redirect );
			exit;
		}
	}

	/**
	 * @param int      $post_id Post ID.
	 * @param \WP_Post $post    Post.
	 * @param bool     $update  Updating existing post.
	 */
	public function clear_finish_setup_flag_on_event_update( $post_id, $post, $update ) {
		if ( ! $update || ! $post_id ) {
			return;
		}
		if ( get_post_meta( $post_id, self::META_FINISH_SETUP, true ) === '1' ) {
			delete_post_meta( $post_id, self::META_FINISH_SETUP );
		}
	}

	/**
	 * When the Setup submenu is removed after the wizard finishes, core cannot infer the parent menu item
	 * for this page. user_can_access_admin_page() then mismatches $_registered_pages and fires
	 * admin_page_access_denied before admin_init (e.g. browser Back to evge-onboarding). Mirror
	 * maybe_redirect_away() here so those requests reach the dashboard instead of a 403.
	 */
	public function redirect_completed_onboarding_on_access_denied() {
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		if ( empty( $_GET['page'] ) || sanitize_key( wp_unslash( $_GET['page'] ) ) !== self::PAGE_SLUG ) {
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$relaunch = isset( $_GET['relaunch'] ) && (string) wp_unslash( $_GET['relaunch'] ) === '1';
		$state    = self::get_state();
		if ( empty( $state[ self::KEY_WIZARD_COMPLETED ] ) || $relaunch ) {
			return;
		}
		// phpcs:enable WordPress.Security.NonceVerification.Recommended
		wp_safe_redirect( admin_url( 'admin.php?page=evge-dashboard' ) );
		exit;
	}

	public function maybe_redirect_away() {
		if ( ! isset( $_GET['page'] ) || sanitize_key( wp_unslash( $_GET['page'] ) ) !== self::PAGE_SLUG ) {
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$relaunch = isset( $_GET['relaunch'] ) && $_GET['relaunch'] === '1';
		$state    = self::get_state();
		if ( ! empty( $state[ self::KEY_WIZARD_COMPLETED ] ) && ! $relaunch ) {
			wp_safe_redirect( admin_url( 'admin.php?page=evge-dashboard' ) );
			exit;
		}

		$step = isset( $_GET['step'] ) ? absint( $_GET['step'] ) : 1;
		if ( $step < 1 || $step > 3 ) {
			wp_safe_redirect( admin_url( 'admin.php?page=' . self::PAGE_SLUG . '&step=1' ) );
			exit;
		}
	}

	public function enqueue_assets( $hook ) {
		if ( strpos( (string) $hook, self::PAGE_SLUG ) === false ) {
			return;
		}
		wp_enqueue_style(
			'evge-onboarding',
			trailingslashit( EVGE_PLUGIN_URL ) . 'assets/css/admin/evge-onboarding.css',
			array(),
			EVGE_VERSION
		);
		wp_enqueue_script(
			'evge-onboarding',
			trailingslashit( EVGE_PLUGIN_URL ) . 'assets/js/admin/evge-onboarding.js',
			array( 'jquery' ),
			EVGE_VERSION,
			true
		);
		wp_localize_script(
			'evge-onboarding',
			'evgeOnboarding',
			array(
				'ajax_url' => admin_url( 'admin-ajax.php' ),
				'nonce'    => wp_create_nonce( 'evge_onboarding' ),
				'page_url' => admin_url( 'admin.php?page=' . self::PAGE_SLUG ),
				'strings'  => array(
					'creating' => __( 'Creating event…', 'event-genius' ),
					'success'  => __( 'Success! Continuing…', 'event-genius' ),
					'error'    => __( 'Something went wrong. Please try again.', 'event-genius' ),
				),
			)
		);
	}

	public function enqueue_checklist_assets( $hook ) {
		if ( ! $this->should_show_checklist_ui() ) {
			return;
		}
		wp_enqueue_style(
			'evge-setup-checklist',
			trailingslashit( EVGE_PLUGIN_URL ) . 'assets/css/admin/evge-setup-checklist.css',
			array(),
			EVGE_VERSION
		);
		wp_enqueue_script(
			'evge-setup-checklist',
			trailingslashit( EVGE_PLUGIN_URL ) . 'assets/js/admin/evge-setup-checklist.js',
			array( 'jquery' ),
			EVGE_VERSION,
			true
		);
	}

	/**
	 * Whether checklist markup should load (assets + partial).
	 */
	public function should_show_checklist_ui() {
		if ( ! function_exists( 'evge_is_free_version' ) || ! evge_is_free_version() ) {
			return false;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
		if ( $page === '' || strpos( $page, 'evge-' ) !== 0 ) {
			return false;
		}
		// Wizard is its own full-screen flow; do not load checklist assets there.
		if ( $page === self::PAGE_SLUG ) {
			return false;
		}
		return true;
	}

	/**
	 * Fired from BasePage::render(); outputs checklist when applicable.
	 *
	 * @param \WPEventGenius\Admin\Page\BasePage $page Admin page instance.
	 */
	public function render_checklist_placeholder( $page ) {
		if ( ! $this->should_show_checklist_for_current_route() ) {
			return;
		}
		include EVGE_ADMIN_TEMPLATE_PATH . 'evge/partials/setup-checklist.php';
	}

	/**
	 * All Event Genius admin screens that use BasePage, except the single-registration detail screen.
	 *
	 * Note: The post-registration admin link uses tab=registrations, subtab=single, id={event} (event-scoped list).
	 * Only registration_id denotes a one-registration drill-down; subtab=single must not hide the checklist there.
	 */
	private function should_show_checklist_for_current_route() {
		if ( ! $this->should_show_checklist_ui() ) {
			return false;
		}
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
		if ( $page === 'evge-registrations' && ! empty( $_GET['registration_id'] ) ) {
			return false;
		}
		// phpcs:enable WordPress.Security.NonceVerification.Recommended
		return true;
	}

	public function render_page() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to access this page.', 'event-genius' ) );
		}

		$step = isset( $_GET['step'] ) ? absint( $_GET['step'] ) : 1;
		$step = min( 3, max( 1, $step ) );

		$total_steps = 3;
		$progress    = $step;

		if ( $step === 3 ) {
			self::set_state_key( self::KEY_WIZARD_COMPLETED, true );
			self::set_state_key( self::KEY_CHECKLIST_INITIATED, true );
		}

		include EVGE_ADMIN_TEMPLATE_PATH . 'evge/onboarding.php';
	}

	/**
	 * Checklist rows for the partial.
	 *
	 * @return array<int, array<string, mixed>>
	 */
	public static function get_checklist() {
		global $wpdb;

		$state             = self::get_state();
		$form_visit_done   = ! empty( $state[ self::KEY_FORM_FIELDS_DONE ] );
		$email_visit_done  = ! empty( $state[ self::KEY_EMAIL_DONE ] );
		$archive_visit_done = ! empty( $state[ self::KEY_EVENT_ARCHIVE_VISIT_DONE ] );

		$has_future = self::has_future_published_event();
		$reg_count  = self::get_registration_count();
		$has_regs   = $reg_count > 0;

		$pending_id = self::get_finish_setup_pending_event_id();
		$details_done = ( $pending_id === 0 );

		$create_event_url = admin_url( 'post-new.php?post_type=' . EVGE_EVENT_POST_TYPE );
		$dashboard_url    = admin_url( 'admin.php?page=evge-registrations' );

		$test_event_url = '';
		if ( $has_future ) {
			$eid = self::get_next_future_event_id();
			if ( $eid ) {
				$test_event_url = get_permalink( $eid );
			}
		}
		if ( ! $test_event_url ) {
			$test_event_url = $create_event_url;
		}

		$form_id       = self::get_default_form_id();
		$form_visit_url = admin_url( 'admin.php?page=evge-registrations&tab=forms&subtab=builder&form_id=' . $form_id . '&evge_checklist_visit=form' );
		$email_visit_url = add_query_arg(
			array(
				'page'                 => 'evge-registrations',
				'tab'                  => 'forms',
				'subtab'               => 'emails',
				'form_id'              => $form_id,
				'evge_checklist_visit' => 'email',
				'evge_fb_focus'        => 'confirmation',
			),
			admin_url( 'admin.php' )
		);
		$archive_visit_url = admin_url( 'admin.php?page=evge-settings&evge_checklist_visit=archive' );

		$edit_pending_url = $pending_id ? get_edit_post_link( $pending_id, 'raw' ) : '';

		if ( $has_regs ) {
			$table = self::registrations_table_name();
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			$row = $wpdb->get_row( "SELECT `event_id` FROM `{$table}` ORDER BY `id` DESC LIMIT 1" );
			if ( $row && isset( $row->event_id ) ) {
				$dashboard_url = Formatter::manage_event_link( absint( $row->event_id ) );
			}
		}

		return array(
			array(
				'id'          => 'upcoming_event',
				'label'       => __( 'Upcoming event created', 'event-genius' ),
				'url'         => $create_event_url,
				'done'        => $has_future,
				'cta_label'   => __( 'Create event', 'event-genius' ),
			),
			array(
				'id'          => 'first_registration',
				'label'       => $has_regs ? __( 'First registration received', 'event-genius' ) : __( 'Receive your first registration', 'event-genius' ),
				'description' => $has_regs ? '' : __( 'Submit a test registration or share your event to see everything working.', 'event-genius' ),
				'url'         => $has_regs ? $dashboard_url : $test_event_url,
				'done'        => $has_regs,
				'cta_label'   => $has_regs ? __( 'View in dashboard', 'event-genius' ) : __( 'View event & test', 'event-genius' ),
			),
			array(
				'id'          => 'add_event_details',
				'label'       => __( 'Add details to your event', 'event-genius' ),
				'description' => __( 'Add description, images, or additional details to improve your event.', 'event-genius' ),
				'url'         => $edit_pending_url,
				'done'        => $details_done,
				'cta_label'   => __( 'Edit event', 'event-genius' ),
			),
			array(
				'id'          => 'customize_form',
				'label'       => __( 'Customize your registration form', 'event-genius' ),
				'description' => __( 'Add or remove fields to match what you need to collect.', 'event-genius' ),
				'url'         => $form_visit_url,
				'done'        => $form_visit_done,
				'cta_label'   => __( 'Customize form', 'event-genius' ),
			),
			array(
				'id'          => 'review_email',
				'label'       => __( 'Review confirmation email', 'event-genius' ),
				'description' => __( 'Edit the message attendees receive after registering.', 'event-genius' ),
				'url'         => $email_visit_url,
				'done'        => $email_visit_done,
				'cta_label'   => __( 'Edit email', 'event-genius' ),
			),
			array(
				'id'          => 'view_event_archive',
				'label'       => __( 'View the default event archive', 'event-genius' ),
				'description' => __( 'See how events appear on your site\'s default calendar (event archive) page.', 'event-genius' ),
				'url'         => $archive_visit_url,
				'done'        => $archive_visit_done,
				'cta_label'   => __( 'View archive', 'event-genius' ),
			),
		);
	}

	/**
	 * Default registration form ID for checklist deep-links.
	 */
	public static function get_default_form_id() {
		$settings = get_option( 'evge_event_settings', array() );
		if ( ! empty( $settings['default_registration_form'] ) ) {
			return max( 1, (int) $settings['default_registration_form'] );
		}
		return 1;
	}

	public static function has_future_published_event() {
		$ids = get_posts(
			array(
				'post_type'      => EVGE_EVENT_POST_TYPE,
				'post_status'    => 'publish',
				'posts_per_page' => 50,
				'fields'         => 'ids',
				'orderby'        => 'ID',
				'order'          => 'DESC',
			)
		);
		$now = time();
		foreach ( $ids as $id ) {
			$end_utc = get_post_meta( $id, 'evge_end_date_utc', true );
			if ( $end_utc && strtotime( $end_utc ) > $now ) {
				return true;
			}
		}
		return false;
	}

	public static function get_next_future_event_id() {
		$ids = get_posts(
			array(
				'post_type'      => EVGE_EVENT_POST_TYPE,
				'post_status'    => 'publish',
				'posts_per_page' => 50,
				'fields'         => 'ids',
				'orderby'        => 'ID',
				'order'          => 'ASC',
			)
		);
		$now = time();
		foreach ( $ids as $id ) {
			$end_utc = get_post_meta( $id, 'evge_end_date_utc', true );
			if ( $end_utc && strtotime( $end_utc ) > $now ) {
				return (int) $id;
			}
		}
		return 0;
	}

	public static function get_registration_count() {
		if ( ! self::registrations_table_exists() ) {
			return 0;
		}

		global $wpdb;
		$table = self::registrations_table_name();
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		return (int) $wpdb->get_var( "SELECT COUNT(*) FROM `{$table}`" );
	}

	/**
	 * Whether to show the inline success banner on the event registrations screen (first registration admin deep-link).
	 */
	public static function should_show_first_registration_admin_notice() {
		if ( ! function_exists( 'evge_is_free_version' ) || ! evge_is_free_version() ) {
			return false;
		}
		if ( ! current_user_can( 'manage_evge_registrations' ) ) {
			return false;
		}
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( empty( $_GET['page'] ) || sanitize_key( wp_unslash( $_GET['page'] ) ) !== 'evge-registrations' ) {
			return false;
		}
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( ! isset( $_GET[ self::QUERY_FIRST_REGISTRATION_ADMIN_SUCCESS ] ) || '1' !== (string) wp_unslash( $_GET[ self::QUERY_FIRST_REGISTRATION_ADMIN_SUCCESS ] ) ) {
			return false;
		}
		return true;
	}

	public static function get_finish_setup_pending_event_id() {
		$ids = get_posts(
			array(
				'post_type'      => EVGE_EVENT_POST_TYPE,
				'post_status'    => 'any',
				'posts_per_page' => 1,
				'fields'         => 'ids',
				'meta_key'       => self::META_FINISH_SETUP,
				'meta_value'     => '1',
			)
		);
		return ! empty( $ids ) ? (int) $ids[0] : 0;
	}

	/**
	 * Cost, capacity, timeline, and attendee-list values for a new event (same sources as the event editor: Settings + Defaults).
	 *
	 * @return array<string, mixed>
	 */
	private static function get_new_event_defaults_from_settings() {
		$currency = Settings::get( 'currency_symbol' );
		if ( null === $currency || '' === $currency ) {
			$currency = Defaults::get( 'currency_symbol' );
		}

		$cost_display = Settings::get( 'cost_display' );
		if ( null === $cost_display || '' === $cost_display ) {
			$cost_display = Defaults::get( 'cost_display' );
		}

		$cap_unlimited = Settings::get( 'capacity_unlimited' );
		if ( null === $cap_unlimited ) {
			$cap_unlimited = Defaults::get( 'capacity_unlimited' );
		}
		$unlimited = ( 'enabled' === $cap_unlimited ) ? 'enabled' : 'disabled';

		$capacity = Settings::get( 'capacity' );
		if ( null === $capacity || '' === $capacity ) {
			$capacity = Defaults::get( 'capacity' );
		}
		$capacity = max( 1, absint( $capacity ) );

		$per_reg = Settings::get( 'capacity_per_registration' );
		if ( null === $per_reg || '' === $per_reg ) {
			$per_reg = Defaults::get( 'capacity_per_registration' );
		}
		$per_reg = max( 1, absint( $per_reg ) );

		$show_list = Settings::get( 'show_attendee_list' );
		if ( null === $show_list || '' === $show_list ) {
			$show_list = Defaults::get( 'show_attendee_list' );
		}
		$show_list = ( 'enabled' === $show_list ) ? 'enabled' : 'disabled';

		$who = Settings::get( 'who_can_see_attendee_list' );
		if ( null === $who || '' === $who ) {
			$who = Defaults::get( 'who_can_see_attendee_list' );
		}
		if ( ! in_array( $who, array( 'everyone', 'logged_in' ), true ) ) {
			$who = 'everyone';
		}

		$open_type = Settings::get( 'open_type' );
		if ( null === $open_type || '' === $open_type ) {
			$open_type = Defaults::get( 'open_type' );
		}
		// Global settings use "immediate"; event meta and EventPost expect "immediately".
		if ( 'immediate' === $open_type ) {
			$open_type = 'immediately';
		}
		if ( ! in_array( $open_type, array( 'immediately', 'relative', 'custom' ), true ) ) {
			$open_type = 'immediately';
		}

		$rel_open_off = Settings::get( 'relative_open_offset' );
		if ( null === $rel_open_off || '' === $rel_open_off ) {
			$rel_open_off = Defaults::get( 'relative_open_offset' );
		}
		$rel_open_off = absint( $rel_open_off );

		$rel_open_unit = Settings::get( 'relative_open_offset_type' );
		if ( null === $rel_open_unit || '' === $rel_open_unit ) {
			$rel_open_unit = Defaults::get( 'relative_open_offset_type' );
		}
		if ( ! in_array( $rel_open_unit, array( 'hours', 'days' ), true ) ) {
			$rel_open_unit = 'days';
		}

		$close_type = Settings::get( 'close_type' );
		if ( null === $close_type || '' === $close_type ) {
			$close_type = Defaults::get( 'close_type' );
		}
		if ( ! in_array( $close_type, array( 'never', 'relative', 'custom' ), true ) ) {
			$close_type = 'relative';
		}

		$rel_close_off = Settings::get( 'relative_close_offset' );
		if ( null === $rel_close_off || '' === $rel_close_off ) {
			$rel_close_off = Defaults::get( 'relative_close_offset' );
		}
		$rel_close_off = absint( $rel_close_off );

		$rel_close_unit = Settings::get( 'relative_close_offset_type' );
		if ( null === $rel_close_unit || '' === $rel_close_unit ) {
			$rel_close_unit = Defaults::get( 'relative_close_offset_type' );
		}
		if ( ! in_array( $rel_close_unit, array( 'hours', 'days' ), true ) ) {
			$rel_close_unit = 'days';
		}

		return array(
			'evge_currency_symbol'            => (string) $currency,
			'evge_cost_amount'                => '',
			'evge_cost_display'               => (string) $cost_display,
			'evge_unlimited_capacity'         => $unlimited,
			'evge_capacity'                   => $capacity,
			'evge_capacity_per_registration'  => $per_reg,
			'evge_show_attendee_list'         => $show_list,
			'evge_who_can_see_attendee_list'  => $who,
			'evge_open_type'                  => $open_type,
			'evge_relative_open_offset'       => $rel_open_off,
			'evge_relative_open_offset_type'  => $rel_open_unit,
			'evge_close_type'                 => $close_type,
			'evge_relative_close_offset'      => $rel_close_off,
			'evge_relative_close_offset_type' => $rel_close_unit,
		);
	}

	public function ajax_create_event() {
		check_ajax_referer( 'evge_onboarding', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Permission denied.', 'event-genius' ) ) );
		}

		$title    = isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : '';
		$date     = isset( $_POST['date'] ) ? sanitize_text_field( wp_unslash( $_POST['date'] ) ) : '';
		$time     = isset( $_POST['time'] ) ? sanitize_text_field( wp_unslash( $_POST['time'] ) ) : '09:00:00';
		$end_date = isset( $_POST['end_date'] ) ? sanitize_text_field( wp_unslash( $_POST['end_date'] ) ) : '';
		$end_time = isset( $_POST['end_time'] ) ? sanitize_text_field( wp_unslash( $_POST['end_time'] ) ) : '17:00:00';

		if ( $title === '' ) {
			$title = __( 'My first event', 'event-genius' );
		}
		if ( $date === '' ) {
			$date = gmdate( 'Y-m-d', strtotime( '+1 day' ) );
		}
		if ( $end_date === '' ) {
			$end_date = $date;
		}
		$time     = strlen( $time ) === 5 ? $time . ':00' : $time;
		$end_time = strlen( $end_time ) === 5 ? $end_time . ':00' : $end_time;

		$start_raw = $date . ' ' . $time;
		$end_raw   = $end_date . ' ' . $end_time;

		$tz = wp_timezone_string();
		if ( ! $tz ) {
			$tz = 'UTC';
		}

		$data = array_merge(
			self::get_new_event_defaults_from_settings(),
			array(
				'evge_start_date'         => $start_raw,
				'evge_end_date'           => $end_raw,
				'evge_timezone'           => $tz,
				'evge_all_day'            => 'disabled',
				'evge_allow_registration' => 'enabled',
				'evge_recurrence_type'    => 'none',
			)
		);

		$sanitized = EventCreate::sanitize_event_data( $data );
		if ( empty( $sanitized['evge_start_date'] ) || empty( $sanitized['evge_end_date'] ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid date or time.', 'event-genius' ) ) );
		}

		$create = new EventCreate(
			array(
				'post_title'  => $title,
				'start_date'  => $sanitized['evge_start_date'],
				'end_date'    => $sanitized['evge_end_date'],
				'timezone'    => $sanitized['evge_timezone'],
				'post_author' => get_current_user_id(),
			)
		);

		$post_id = $create->insert_new_post();
		if ( ! $post_id ) {
			wp_send_json_error( array( 'message' => __( 'Could not create the event.', 'event-genius' ) ) );
		}

		EventCreate::update_event_meta( $post_id, $sanitized );

		$form_id = self::get_default_form_id();
		update_post_meta( $post_id, 'evge_registration_form', $form_id );

		update_post_meta( $post_id, self::META_FINISH_SETUP, '1' );

		$link = get_permalink( $post_id );
		$url  = $link ? $link : get_edit_post_link( $post_id, 'raw' );
		set_transient( self::TRANSIENT_SUCCESS_URL, $url, 300 );
		set_transient( self::TRANSIENT_SUCCESS_EVENT_ID, (string) $post_id, 300 );

		wp_send_json_success(
			array(
				'event_id' => $post_id,
				'url'      => $url,
			)
		);
	}
}
