<?php
/**
 * File Path: includes/export/class-mbs-book-bible-exporter.php
 *
 * Book Bible Exporter
 *
 * Thin orchestrator: wires AJAX hook.
 * Delegates data gathering to MBS_Book_Bible_Data_Gatherer and sheet
 * population to MBS_Book_Bible_Tab_Writer. PRO/PUB gated. Streamed --
 * no temp file on disk.
 *
 * Instantiated once by MBS_Plugin::load_admin(). Constructor self-registers
 * all hooks.
 *
 * @package MyBookShowroom
 * @since   1.2.0
 */

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

/**
 * Class MBS_Book_Bible_Exporter
 *
 * @since 1.2.0
 */
class MBS_Book_Bible_Exporter {

	/** @var self|null Singleton instance. */
	private static ?self $instance = null;

	/**
	 * Return the singleton instance.
	 *
	 * @return self
	 */
	public static function get_instance(): self {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor. Self-registers all WP hooks.
	 */
	private function __construct() {
		add_action( 'wp_ajax_mbs_export_book_bible', [ $this, 'handle_ajax' ] );
	}

	// -------------------------------------------------------------------------
	// Public hooks
	// -------------------------------------------------------------------------

	/**
	 * AJAX handler. Streams XLSX bytes directly -- no temp file on disk.
	 *
	 * @return void Does not return.
	 */
	public function handle_ajax(): void {
		check_ajax_referer( 'mbs_export_book_bible', 'nonce' );

		if ( ! mbs_is_pro() ) {
			wp_send_json_error(
				[ 'message' => __( 'PRO or PUB license required.', 'my-book-showroom' ) ],
				403
			);
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce checked above
		$post_id = absint( $_GET['post_id'] ?? $_POST['post_id'] ?? 0 );

		if ( ! $post_id || get_post_type( $post_id ) !== MBS_POST_TYPE ) {
			wp_send_json_error(
				[ 'message' => __( 'Invalid book.', 'my-book-showroom' ) ],
				400
			);
		}

		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			wp_send_json_error(
				[ 'message' => __( 'Permission denied.', 'my-book-showroom' ) ],
				403
			);
		}

		// Pre-flight: ZipArchive is required to build XLSX (which is a ZIP archive).
		// Virtually all managed WordPress hosts enable php_zip by default; this guard
		// exists for edge-case server configurations and gives a clear action message
		// rather than an uncaught RuntimeException.
		if ( ! class_exists( 'ZipArchive' ) ) {
			wp_send_json_error(
				[ 'message' => __( 'The PHP zip extension is not enabled on this server. Please ask your host to enable php_zip, then try again.', 'my-book-showroom' ) ],
				500
			);
		}

		$data    = ( new MBS_Book_Bible_Data_Gatherer() )->gather( $post_id );
		$builder = MBS_Book_Bible_Tab_Writer::make()->build( $data );
		$bytes   = $builder->build();
		$slug    = sanitize_title( get_the_title( $post_id ) );
		$date    = gmdate( 'Y-m-d' );
		$fname   = "{$slug}-book-bible-{$date}.xlsx";

		header( 'Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' );
		header( 'Content-Disposition: attachment; filename="' . $fname . '"' );
		header( 'Content-Length: ' . strlen( $bytes ) );
		header( 'Cache-Control: no-store, no-cache' );
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- binary stream
		echo $bytes;
		exit;
	}

	/**
	 * Add "Book Bible" row action to the book list table. PRO/PUB only.
	 *
	 * NOTE: intentionally unhooked from post_row_actions. Book Bible export
	 * is accessible from the book editor only. Retained for future UX redesign.
	 *
	 * @param array   $actions Existing row actions.
	 * @param WP_Post $post    Current post object.
	 * @return array
	 */
	public function add_row_action( array $actions, WP_Post $post ): array {
		if ( MBS_POST_TYPE !== $post->post_type )             return $actions;
		if ( ! mbs_is_pro() )                                return $actions;
		if ( ! current_user_can( 'edit_post', $post->ID ) )  return $actions;

		$nonce = wp_create_nonce( 'mbs_export_book_bible' );
		$url   = add_query_arg(
			[
				'action'  => 'mbs_export_book_bible',
				'post_id' => $post->ID,
				'nonce'   => $nonce,
			],
			admin_url( 'admin-ajax.php' )
		);

		$actions['mbs_book_bible'] = '<a href="' . esc_url( $url ) . '">' .
			esc_html__( 'Book Bible', 'my-book-showroom' ) . '</a>';

		return $actions;
	}
}
