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

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

/**
 * Handles the admin-side wiring for the booking instances CSV importer.
 *
 * Mirrors WC_Bookings_Admin_Exporters: a hidden submenu page hosts the multi-step
 * import flow, an AJAX endpoint drives the batched processing, and an "Import" button
 * appears on the Bookings list screen alongside the existing "Export" button.
 *
 * @version 3.6.0
 */
class WC_Bookings_Admin_Importers {

	/**
	 * Submenu page slug for the importer screen.
	 */
	const PAGE_SLUG = 'bookings_importer';

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

	/**
	 * Constructor.
	 */
	public function __construct() {
		if ( ! $this->import_allowed() ) {
			return;
		}

		// 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_import' ) );

		// WordPress-core importer registration (Tools → Import).
		add_action( 'admin_init', array( $this, 'register_importers' ) );

		// Process step.
		add_action( 'wp_ajax_woocommerce_bookings_do_ajax_import', array( $this, 'do_ajax_import' ) );

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

		// Register import script.
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
	}

	/**
	 * Whether the current user can import bookings.
	 *
	 * @return bool
	 */
	protected function import_allowed() {
		return current_user_can( 'manage_woocommerce' ) && current_user_can( 'import' );
	}

	/**
	 * Whether we are currently on the Bookings list screen.
	 *
	 * @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 importer screen.
	 *
	 * @return bool
	 */
	protected function is_import_screen() {
		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		return $screen && 'wc_booking_page_' . self::PAGE_SLUG === $screen->id;
	}

	/**
	 * Register the hidden importer submenu page.
	 */
	public function add_to_menus() {
		add_submenu_page(
			self::PARENT_MENU,
			__( 'Import Bookings', 'woocommerce-bookings' ),
			__( 'Import Bookings', 'woocommerce-bookings' ),
			'import',
			self::PAGE_SLUG,
			array( $this, 'render_import_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 importer screen.
	 */
	public function menu_highlight_for_import() {
		global $submenu_file;

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

	/**
	 * Register the importer with WordPress core's Tools → Import screen.
	 */
	public function register_importers() {
		if ( defined( 'WP_LOAD_IMPORTERS' ) ) {
			register_importer(
				'woocommerce_bookings_csv',
				__( 'WooCommerce Bookings (CSV)', 'woocommerce-bookings' ),
				__( 'Import <strong>bookings</strong> to your store via a csv file.', 'woocommerce-bookings' ),
				array( $this, 'render_import_page' )
			);
		}
	}

	/**
	 * Register the import script (enqueued lazily on the import step).
	 */
	public function admin_scripts() {
		$asset_file = WC_BOOKINGS_ABSPATH . 'dist/admin-import-bookings.asset.php';
		$asset      = file_exists( $asset_file )
			? include $asset_file
			: array(
				'dependencies' => array( 'jquery' ),
				'version'      => WC_BOOKINGS_VERSION,
			);

		wp_register_script(
			'wc_bookings_admin_import_js',
			WC_BOOKINGS_PLUGIN_URL . '/dist/admin-import-bookings.js',
			array_unique( array_merge( $asset['dependencies'], array( 'jquery' ) ) ),
			$asset['version'],
			true
		);

		// The .woocommerce-progress-form-wrapper / wc-progress-steps / woocommerce-importer styles ship in WC core's
		// admin stylesheet. Custom CPT submenu pages don't get it for free, so enqueue it on the importer screen.
		if ( $this->is_import_screen() ) {
			wp_enqueue_style( 'woocommerce_admin_styles' );
		}
	}

	/**
	 * Render the importer screen — delegates to WC_Bookings_CSV_Importer_Controller.
	 */
	public function render_import_page() {
		// Tools → Import lands here via WordPress; redirect to the dedicated screen.
		if ( defined( 'WP_LOAD_IMPORTERS' ) ) {
			wp_safe_redirect( admin_url( 'edit.php?post_type=wc_booking&page=' . self::PAGE_SLUG ) );
			exit;
		}

		include_once WC_BOOKINGS_ABSPATH . 'includes/admin/import/class-wc-bookings-csv-importer.php';

		$importer = new WC_Bookings_CSV_Importer_Controller();
		$importer->dispatch();
	}

	/**
	 * Inject an "Import" button on the Bookings list screen as a `page-title-action`.
	 */
	public function render_list_screen_button() {
		if ( ! $this->is_bookings_list_screen() ) {
			return;
		}

		$import_url = add_query_arg(
			array(
				'post_type' => 'wc_booking',
				'page'      => self::PAGE_SLUG,
			),
			admin_url( 'edit.php' )
		);
		$label      = __( 'Import', 'woocommerce-bookings' );

		?>
		<script type="text/javascript">
			jQuery( function ( $ ) {
				var importUrl = <?php echo wp_json_encode( esc_url_raw( $import_url ) ); ?>;
				var importLabel = <?php echo wp_json_encode( $label ); ?>;
				var $button = $( '<a class="page-title-action wc-bookings-importer-button"></a>' )
					.attr( 'href', importUrl )
					.text( importLabel );

				// Place the Import button between "Add Booking" and "Export". When the Export button is missing
				// (e.g. user without the export cap), fall back to appending after the last page-title-action.
				var $exportButton = $( '.wc-bookings-exporter-button' );

				if ( $exportButton.length ) {
					$button.insertBefore( $exportButton );
				} else {
					var $anchor = $( '.wrap > .page-title-action' ).last();
					if ( $anchor.length ) {
						$button.insertAfter( $anchor );
					} else {
						$button.insertAfter( $( '.wp-heading-inline' ).filter( ':first' ) );
					}
				}
			} );
		</script>
		<?php
	}

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

		if ( ! $this->import_allowed() || ! isset( $_POST['file'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified above.
			wp_send_json_error( array( 'message' => __( 'Insufficient privileges to import bookings.', 'woocommerce-bookings' ) ) );
		}

		include_once WC_BOOKINGS_ABSPATH . 'includes/admin/import/class-wc-bookings-csv-importer-controller.php';
		include_once WC_BOOKINGS_ABSPATH . 'includes/admin/import/class-wc-bookings-csv-importer.php';

		$file   = wc_clean( wp_unslash( $_POST['file'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
		$params = array(
			'delimiter'       => ! empty( $_POST['delimiter'] ) ? wc_clean( wp_unslash( $_POST['delimiter'] ) ) : ',', // phpcs:ignore WordPress.Security.NonceVerification.Missing
			'start_pos'       => isset( $_POST['position'] ) ? absint( $_POST['position'] ) : 0, // phpcs:ignore WordPress.Security.NonceVerification.Missing
			'mapping'         => isset( $_POST['mapping'] ) ? (array) wc_clean( wp_unslash( $_POST['mapping'] ) ) : array(), // phpcs:ignore WordPress.Security.NonceVerification.Missing
			'update_existing' => isset( $_POST['update_existing'] ) ? (bool) $_POST['update_existing'] : false, // phpcs:ignore WordPress.Security.NonceVerification.Missing
			/**
			 * Filters the per-batch row limit for the bookings CSV importer.
			 *
			 * @since 3.6.0
			 *
			 * @param int $lines Number of rows to process per AJAX batch.
			 */
			'lines'           => apply_filters( 'woocommerce_bookings_import_batch_size', 30 ),
			'parse'           => true,
		);

		// Persist the running error and warning logs so the "done" screen can show them.
		if ( 0 !== $params['start_pos'] ) {
			$error_log   = array_filter( (array) get_user_option( 'bookings_import_error_log' ) );
			$warning_log = array_filter( (array) get_user_option( 'bookings_import_warning_log' ) );
		} else {
			$error_log   = array();
			$warning_log = array();
		}

		$importer         = WC_Bookings_CSV_Importer_Controller::get_importer( $file, $params );
		$results          = $importer->import();
		$percent_complete = $importer->get_percent_complete();
		$error_log        = array_merge( $error_log, $results['failed'], $results['skipped'] );
		$warning_log      = array_merge( $warning_log, $results['warnings'] );

		update_user_option( get_current_user_id(), 'bookings_import_error_log', $error_log );
		update_user_option( get_current_user_id(), 'bookings_import_warning_log', $warning_log );

		if ( 100 === $percent_complete ) {
			wp_delete_file( $file );

			wp_send_json_success(
				array(
					'position'   => 'done',
					'percentage' => 100,
					'url'        => add_query_arg(
						array( '_wpnonce' => wp_create_nonce( 'woocommerce-bookings-csv-importer' ) ),
						admin_url( 'edit.php?post_type=wc_booking&page=' . self::PAGE_SLUG . '&step=done' )
					),
					'imported'   => count( $results['imported'] ),
					'failed'     => count( $results['failed'] ),
					'updated'    => count( $results['updated'] ),
					'skipped'    => count( $results['skipped'] ),
				)
			);
		} else {
			wp_send_json_success(
				array(
					'position'   => $importer->get_file_position(),
					'percentage' => $percent_complete,
					'imported'   => count( $results['imported'] ),
					'failed'     => count( $results['failed'] ),
					'updated'    => count( $results['updated'] ),
					'skipped'    => count( $results['skipped'] ),
				)
			);
		}
	}
}
