<?php
namespace Pay4All\Pro\Integrations\Age;

use Pay4All\Age\Admin\UserProfile;
use Pay4All\Age\Services\Config;
use Pay4All\Age\Services\Kyc;
use Pay4All\Age\Storage\KycStorage;

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

/**
 * Full-width "Age verification" panel on the WooCommerce order edit
 * screen — rendered as a metabox in the `normal` (main) column with
 * `high` priority, so it stacks directly under WooCommerce's own
 * "Order details" postbox and spans the full editing area (rather
 * than being squeezed inside the shipping-address column of the
 * details postbox as we tried before).
 *
 * Works on both the classic order-edit screen (shop_order CPT) and
 * the WooCommerce HPOS order-edit screen (`woocommerce_page_wc-
 * orders`) because `add_meta_boxes` fires with the correct screen id
 * on both.
 */
final class OrderMetabox {

	public static function register() : void {
		// Priority 30 → fires AFTER WooCommerce registers its own
		// metaboxes at priority 20, so our `high` slot lands right
		// below WC's high-priority Order details postbox.
		add_action( 'add_meta_boxes', [ __CLASS__, 'register_metabox' ], 30, 2 );

		// Inject the lightbox modal once per order-edit page load, on
		// both classic and HPOS screens. The users-list screen has its
		// own hook in UserProfile so this only fires on order pages.
		add_action( 'admin_footer-post.php',                          [ __CLASS__, 'maybe_render_lightbox' ] );
		add_action( 'admin_footer-woocommerce_page_wc-orders',        [ __CLASS__, 'maybe_render_lightbox' ] );
		// Enqueue the lightbox CSS/JS BEFORE the footer runs, otherwise
		// the click handler is never bound and the merchant can't open
		// the modal. Scoped to shop_order + HPOS wc-orders screens.
		add_action( 'admin_enqueue_scripts',                          [ __CLASS__, 'maybe_enqueue_lightbox' ] );
	}

	/**
	 * `admin_enqueue_scripts` handler — enqueues the lightbox assets on
	 * the classic `shop_order` CPT edit and on the HPOS wc-orders edit
	 * screen. Uses the `$hook_suffix` argument WordPress passes to the
	 * hook (reliable) with a `get_current_screen()` fallback (also
	 * checks `post_type` to distinguish shop_order from other CPTs on
	 * `post.php`). This double-check saved the day on installs where
	 * `get_current_screen()` was still empty at enqueue time.
	 *
	 * @param string $hook_suffix Passed by WP core to the hook.
	 */
	public static function maybe_enqueue_lightbox( $hook_suffix = '' ) : void {
		$hook_suffix = (string) $hook_suffix;

		// HPOS wc-orders edit — hook suffix matches the screen id.
		if ( $hook_suffix === 'woocommerce_page_wc-orders' ) {
			UserProfile::enqueue_lightbox_assets();
			return;
		}

		// Classic shop_order CPT — hook suffix is post.php / post-new.php,
		// then check post_type via get_current_screen() to avoid enqueueing
		// on every classic CPT edit page.
		if ( in_array( $hook_suffix, [ 'post.php', 'post-new.php' ], true ) ) {
			$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
			if ( $screen && $screen->post_type === 'shop_order' ) {
				UserProfile::enqueue_lightbox_assets();
			}
		}
	}

	/**
	 * The `admin_footer-post.php` hook fires on every classic CPT edit
	 * screen, not just orders. Guard by screen id before emitting the
	 * modal so we don't pollute unrelated post-type editors.
	 */
	public static function maybe_render_lightbox() : void {
		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		if ( ! $screen ) { return; }
		if ( ! in_array( $screen->id, [ 'shop_order', 'woocommerce_page_wc-orders' ], true ) ) { return; }
		UserProfile::render_lightbox_assets();
	}

	public static function register_metabox( string $screen_id, $post_or_order ) : void {
		if ( ! current_user_can( 'manage_woocommerce' ) ) { return; }

		// HPOS screen id: `woocommerce_page_wc-orders`. Classic CPT: `shop_order`.
		$targets = [ 'shop_order', 'woocommerce_page_wc-orders' ];
		if ( ! in_array( $screen_id, $targets, true ) ) { return; }

		$order_id = self::extract_order_id( $post_or_order );
		if ( ! $order_id ) { return; }

		// Show the metabox whenever the order requires age verification —
		// either photos already exist (order or user bucket) OR the order
		// contains at least one age-restricted product. That way the panel
		// still shows for orders whose customer never uploaded the docs,
		// giving the merchant a visible marker that something is missing.
		$has_order_photos = ! empty( KycStorage::stored_slots( $order_id ) );
		$verified_user_id = (int) get_post_meta( $order_id, '_pay4all_age_verified_from_user', true );
		$has_user_photos  = $verified_user_id > 0
			&& ! empty( KycStorage::user_stored_slots( $verified_user_id ) );
		$order_needs_kyc  = self::order_has_age_restricted_item( $order_id );

		if ( ! $has_order_photos && ! $has_user_photos && ! $order_needs_kyc ) { return; }

		add_meta_box(
			'p4all-age-order',
			esc_html( Config::text( 'order_meta_heading' ) ),
			[ __CLASS__, 'render' ],
			$targets,
			'normal',
			'high'
		);
	}

	/**
	 * True when the order contains at least one item flagged as age-
	 * restricted. Uses `Kyc::is_product_age_required` which is WPML /
	 * Polylang aware, so translated products still resolve correctly.
	 */
	private static function order_has_age_restricted_item( int $order_id ) : bool {
		if ( ! function_exists( 'wc_get_order' ) ) { return false; }
		$order = wc_get_order( $order_id );
		if ( ! $order || ! method_exists( $order, 'get_items' ) ) { return false; }
		foreach ( $order->get_items() as $item ) {
			$product_id = 0;
			if ( is_object( $item ) && method_exists( $item, 'get_product_id' ) ) {
				$product_id = (int) $item->get_product_id();
			}
			if ( $product_id > 0 && Kyc::is_product_age_required( $product_id ) ) {
				return true;
			}
		}
		return false;
	}

	private static function extract_order_id( $post_or_order ) : int {
		if ( is_object( $post_or_order ) && method_exists( $post_or_order, 'get_id' ) ) {
			return (int) $post_or_order->get_id();
		}
		if ( is_object( $post_or_order ) && isset( $post_or_order->ID ) ) {
			return (int) $post_or_order->ID;
		}
		return 0;
	}

	public static function render( $post_or_order ) : void {
		$order_id = self::extract_order_id( $post_or_order );
		if ( ! $order_id ) { return; }

		$order_photos     = UserProfile::order_photos( $order_id );
		$verified_user_id = (int) get_post_meta( $order_id, '_pay4all_age_verified_from_user', true );
		$user_photos      = $verified_user_id > 0 ? UserProfile::user_photos( $verified_user_id ) : [];

		// Prefer order-scoped photos when both exist — they represent the
		// exact verification bound to *this* order. Otherwise fall back
		// to the customer's account bucket.
		$photos = ! empty( $order_photos ) ? $order_photos : $user_photos;

		$has_photos        = ! empty( $photos );
		$has_verified_user = ! empty( $user_photos );

		$user       = $verified_user_id > 0 ? get_userdata( $verified_user_id ) : null;
		$user_label = $user ? ( $user->display_name ?: $user->user_login ) : '';

		$title_for_lightbox = $user_label !== '' ? $user_label : '#' . $order_id;
		?>
		<p style="margin:0 0 6px;color:#3c434a;">
			<?php echo esc_html( Config::text( 'order_meta_intro' ) ); ?>
		</p>
		<?php if ( $has_verified_user ) : ?>
			<p style="margin:0 0 10px;color:#3c434a;">
				<?php echo esc_html( Config::text( 'order_meta_reusable' ) ); ?>
			</p>
		<?php endif; ?>

		<?php if ( $has_photos ) : ?>
			<div style="display:flex;align-items:center;gap:10px;margin:0;">
				<?php echo UserProfile::shield_button_html( $title_for_lightbox, $photos, null, $order_id ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML built with proper escaping in the helper. ?>
				<span style="color:#3c434a;font-size:13px;">
					<?php echo esc_html( Config::text( 'order_meta_click_hint' ) ); ?>
				</span>
			</div>
		<?php else : ?>
			<p style="margin:8px 0 0;color:#a85a00;font-weight:600;">
				<span class="dashicons dashicons-warning" style="color:#dba617;"></span>
				<?php echo esc_html( Config::text( 'order_meta_no_photos' ) ); ?>
			</p>
		<?php endif; ?>
		<?php
		// Render the lightbox modal HTML inline within the metabox
		// rather than relying on `admin_footer-woocommerce_page_wc-
		// orders`, which does NOT fire reliably on WooCommerce HPOS
		// pages. The modal is `position:fixed` so it overlays the
		// full viewport regardless of where it lives in the DOM. Always
		// printed so a future JS caller can still open it even when the
		// initial page has no `$has_photos = true` branch.
		UserProfile::render_lightbox_assets();
		?>
		<script>
		// Reorder the postbox so it appears just above the WooCommerce
		// "Order items" metabox (`#woocommerce-order-items`) rather than
		// below it. WC registers Order data → Order items at priority
		// 20; our metabox comes in at priority 30 which stacks it last.
		// This one-shot DOM move fixes that without touching WC's
		// registration order — safe with theme overrides and with HPOS.
		(function () {
			var box = document.getElementById('p4all-age-order');
			var items = document.getElementById('woocommerce-order-items');
			if (!box || !items) return;
			if (box.parentNode !== items.parentNode) return;
			if (box.nextElementSibling === items) return; // already right above items
			items.parentNode.insertBefore(box, items);
		})();
		</script>
		<?php
	}
}
