<?php
/**
 * WC_Bookings_Admin_Exporters class
 *
 * @package WooCommerce Bookings
 * @since 3.6.0
 */

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

/**
 * Handles the admin-side wiring for the booking instances CSV exporter.
 *
 * Mirrors WC core's WC_Admin_Exporters: a hidden submenu page renders the export form,
 * one AJAX endpoint drives the multi-step batch export, and an admin_init hook serves
 * the generated file. The screen entry point is the WP CPT list table for `wc_booking`.
 *
 * @version 3.6.0
 */
class WC_Bookings_Admin_Exporters {

	/**
	 * Submenu page slug for the export screen.
	 */
	const PAGE_SLUG = 'bookings_exporter';

	/**
	 * Parent menu the export page is hung off (matches the Bookings CPT list).
	 */
	const PARENT_MENU = 'edit.php?post_type=wc_booking';

	/**
	 * URL parameters from the Bookings list table that the export should mirror.
	 *
	 * Keys correspond to the WP-core month/status dropdowns and the
	 * `restrict_manage_posts` filter registered by WC_Bookings_CPT.
	 *
	 * @var string[]
	 */
	const FILTER_PARAMS = array( 'm', 'post_status', 'filter_bookings' );

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'admin_init', array( $this, 'download_export_file' ) );

		// Menu wiring (page exists, menu item hidden).
		add_action( 'admin_menu', array( $this, 'add_to_menus' ) );
		add_action( 'admin_head', array( $this, 'hide_from_menus' ) );
		add_action( 'admin_head', array( $this, 'menu_highlight_for_export' ) );

		// Process step.
		add_action( 'wp_ajax_woocommerce_bookings_do_ajax_export', array( $this, 'do_ajax_export' ) );

		// Inject "Export" button on the Bookings list screen.
		add_action( 'admin_footer-edit.php', array( $this, 'render_list_screen_button' ) );

		// Enqueue export script on the export page.
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
	}

	/**
	 * Whether the current user is allowed to export bookings.
	 *
	 * @return bool
	 */
	protected function export_allowed() {
		return current_user_can( 'manage_woocommerce' ) && current_user_can( 'export' );
	}

	/**
	 * Whether we are currently on the Bookings list screen (`edit.php?post_type=wc_booking`).
	 *
	 * @return bool
	 */
	protected function is_bookings_list_screen() {
		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		return $screen && 'edit-wc_booking' === $screen->id;
	}

	/**
	 * Whether we are currently on the dedicated export screen.
	 *
	 * @return bool
	 */
	protected function is_export_screen() {
		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		return $screen && 'wc_booking_page_' . self::PAGE_SLUG === $screen->id;
	}

	/**
	 * Register the hidden export submenu page.
	 */
	public function add_to_menus() {
		if ( ! $this->export_allowed() ) {
			return;
		}

		add_submenu_page(
			self::PARENT_MENU,
			__( 'Export Bookings', 'woocommerce-bookings' ),
			__( 'Export Bookings', 'woocommerce-bookings' ),
			'export',
			self::PAGE_SLUG,
			array( $this, 'render_export_page' )
		);
	}

	/**
	 * Hide the submenu item — the page exists but isn't reachable from the nav.
	 */
	public function hide_from_menus() {
		global $submenu;

		if ( isset( $submenu[ self::PARENT_MENU ] ) ) {
			foreach ( $submenu[ self::PARENT_MENU ] as $key => $menu_item ) {
				if ( self::PAGE_SLUG === $menu_item[2] ) {
					unset( $submenu[ self::PARENT_MENU ][ $key ] );
				}
			}
		}
	}

	/**
	 * Highlight Bookings → All Bookings while on the export screen.
	 */
	public function menu_highlight_for_export() {
		global $submenu_file;

		if ( $this->is_export_screen() ) {
			$submenu_file = self::PARENT_MENU; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
		}
	}

	/**
	 * Enqueue export script + localised params on the export screen.
	 */
	public function enqueue_assets() {
		if ( ! $this->is_export_screen() || ! $this->export_allowed() ) {
			return;
		}

		$asset_file = WC_BOOKINGS_ABSPATH . 'dist/admin-export-bookings.asset.php';
		$asset      = file_exists( $asset_file )
			? include $asset_file
			: array(
				'dependencies' => array( 'jquery', 'wc-enhanced-select' ),
				'version'      => WC_BOOKINGS_VERSION,
			);

		wp_enqueue_script(
			'wc_bookings_admin_export_js',
			WC_BOOKINGS_PLUGIN_URL . '/dist/admin-export-bookings.js',
			array_unique( array_merge( $asset['dependencies'], array( 'jquery', 'wc-enhanced-select' ) ) ),
			$asset['version'],
			true
		);

		wp_localize_script(
			'wc_bookings_admin_export_js',
			'wc_bookings_export_params',
			array(
				'ajax_url'     => admin_url( 'admin-ajax.php' ),
				'export_nonce' => wp_create_nonce( 'wc-bookings-export' ),
			)
		);

		// Reuse core admin styles for the .woocommerce-exporter form.
		wp_enqueue_style( 'woocommerce_admin_styles' );
	}

	/**
	 * Inject an "Export" button on the Bookings list screen as a `page-title-action`.
	 *
	 * Carries over the active list-table filter URL params so they pre-populate on the export screen.
	 */
	public function render_list_screen_button() {
		if ( ! $this->is_bookings_list_screen() || ! $this->export_allowed() ) {
			return;
		}

		$query = array(
			'post_type' => 'wc_booking',
			'page'      => self::PAGE_SLUG,
		);

		$query = array_merge( $query, self::get_request_filters() );

		$export_url    = add_query_arg( $query, admin_url( 'edit.php' ) );
		$default_label = __( 'Export', 'woocommerce-bookings' );
		/* translators: %d: number of selected bookings */
		$selected_tpl   = __( 'Export %d items', 'woocommerce-bookings' );
		$selected_nonce = wp_create_nonce( 'export-selected-bookings' );

		?>
		<script type="text/javascript">
			jQuery( function ( $ ) {
				var defaultUrl    = <?php echo wp_json_encode( esc_url_raw( $export_url ) ); ?>;
				var defaultLabel  = <?php echo wp_json_encode( $default_label ); ?>;
				var selectedTpl   = <?php echo wp_json_encode( $selected_tpl ); ?>;
				var selectedNonce = <?php echo wp_json_encode( $selected_nonce ); ?>;

				var $button = $( '<a class="page-title-action wc-bookings-exporter-button"></a>' )
					.attr( 'href', defaultUrl )
					.text( defaultLabel );
				var $anchor = $( '.wrap > .page-title-action' ).last();

				if ( $anchor.length ) {
					$button.insertAfter( $anchor );
				} else {
					$button.insertAfter( $( '.wp-heading-inline' ).filter( ':first' ) );
				}

				$( '#posts-filter' ).on(
					'change',
					'#the-list input[type="checkbox"][name="post[]"], #cb-select-all-1, #cb-select-all-2',
					function () {
						setTimeout( function () {
							var ids = $( '#the-list input[type="checkbox"][name="post[]"]:checked' ).map( function () {
								return $( this ).val();
							} ).get();

							if ( ids.length > 0 ) {
								var url = new URL( defaultUrl );
								url.searchParams.set( 'booking_ids', ids.join( ',' ) );
								url.searchParams.set( '_wpnonce', selectedNonce );
								$button
									.attr( 'href', url.toString() )
									.text( selectedTpl.replace( '%d', ids.length ) );
							} else {
								$button.attr( 'href', defaultUrl ).text( defaultLabel );
							}
						}, 0 );
					}
				);
			} );
		</script>
		<?php
	}

	/**
	 * Render the export page.
	 */
	public function render_export_page() {
		include_once WC_BOOKINGS_ABSPATH . 'includes/admin/export/class-wc-bookings-csv-exporter.php';
		include WC_BOOKINGS_ABSPATH . 'includes/admin/views/html-admin-page-bookings-export.php';
	}

	/**
	 * Read the Bookings list filters that were passed through to the export screen via URL.
	 *
	 * @return array Sanitized filter values keyed by FILTER_PARAMS. Empty values are omitted.
	 */
	public static function get_request_filters() {
		$filters = array();

		foreach ( self::FILTER_PARAMS as $param ) {
			// Read-only carry-over of list-table URL params; no nonce involved.
			if ( ! isset( $_GET[ $param ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
				continue;
			}
			$value = wc_clean( wp_unslash( $_GET[ $param ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			if ( '' !== $value && '0' !== (string) $value ) {
				$filters[ $param ] = $value;
			}
		}

		return $filters;
	}

	/**
	 * Serve the generated CSV file.
	 */
	public function download_export_file() {
		if ( ! $this->export_allowed() ) {
			return;
		}

		if (
			isset( $_GET['action'], $_GET['nonce'] ) &&
			'download_bookings_csv' === wc_clean( wp_unslash( $_GET['action'] ) ) &&
			wp_verify_nonce( wc_clean( wp_unslash( $_GET['nonce'] ) ), 'bookings-csv' )
		) {
			include_once WC_BOOKINGS_ABSPATH . 'includes/admin/export/class-wc-bookings-csv-exporter.php';
			$exporter = new WC_Bookings_CSV_Exporter();

			if ( ! empty( $_GET['filename'] ) ) {
				$exporter->set_filename( wc_clean( wp_unslash( $_GET['filename'] ) ) );
			}

			$exporter->export();
		}
	}

	/**
	 * AJAX callback for processing one batch of the export.
	 */
	public function do_ajax_export() {
		check_ajax_referer( 'wc-bookings-export', 'security' );

		if ( ! $this->export_allowed() ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient privileges to export bookings.', 'woocommerce-bookings' ) ) );
		}

		include_once WC_BOOKINGS_ABSPATH . 'includes/admin/export/class-wc-bookings-csv-exporter.php';

		$step     = isset( $_POST['step'] ) ? absint( $_POST['step'] ) : 1;
		$exporter = new WC_Bookings_CSV_Exporter();
		$exporter->set_column_names( $exporter->get_default_column_names() );

		if ( ! empty( $_POST['selected_columns'] ) ) {
			$selected_columns = is_array( $_POST['selected_columns'] )
				? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_columns'] ) )
				: array( sanitize_text_field( wp_unslash( $_POST['selected_columns'] ) ) );
			$exporter->set_columns_to_export( $selected_columns );
		}

		// Explicit booking-ID selection (from the list-table checkboxes) bypasses all filters.
		if ( ! empty( $_POST['booking_ids'] ) ) {
			$raw_ids = is_array( $_POST['booking_ids'] )
				? array_map( 'absint', wp_unslash( $_POST['booking_ids'] ) )
				: array_map( 'absint', explode( ',', sanitize_text_field( wp_unslash( $_POST['booking_ids'] ) ) ) );
			$exporter->set_booking_ids_to_export( $raw_ids );
		}

		$exporter->set_filters( $_POST );

		if ( isset( $_POST['export_meta'] ) && '1' === $_POST['export_meta'] ) {
			$exporter->set_export_meta( true );
		}

		if ( ! empty( $_POST['filename'] ) ) {
			$exporter->set_filename( wc_clean( wp_unslash( $_POST['filename'] ) ) );
		}

		$exporter->set_page( $step );
		$exporter->generate_file();

		/**
		 * Filters the query args appended to the bookings CSV download URL.
		 *
		 * @since 3.6.0
		 *
		 * @param array $query_args Query arguments used to build the download URL.
		 */
		$query_args = apply_filters(
			'woocommerce_bookings_export_get_ajax_query_args',
			array(
				'nonce'    => wp_create_nonce( 'bookings-csv' ),
				'action'   => 'download_bookings_csv',
				'filename' => $exporter->get_filename(),
			)
		);

		if ( 100 === $exporter->get_percent_complete() ) {
			wp_send_json_success(
				array(
					'step'       => 'done',
					'percentage' => 100,
					'url'        => add_query_arg( $query_args, admin_url( 'edit.php?post_type=wc_booking' ) ),
				)
			);
		} else {
			wp_send_json_success(
				array(
					'step'       => ++$step,
					'percentage' => $exporter->get_percent_complete(),
					'columns'    => $exporter->get_column_names(),
				)
			);
		}
	}
}
