<?php
/**
 * Shipping address label print view.
 *
 * @package WPDudeProducts
 */

declare(strict_types=1);

namespace WPDude\Products\Admin;

use WPDude\Products\Orders\Order_Repository;
use WPDude\Products\Support\Countries;

/**
 * Printable shipping address label for fulfilment (HTML + browser print).
 */
final class Shipping_Label_Page {

	public const PAGE_SLUG = 'dude-commerce-shipping-label';

	/**
	 * Register hooks.
	 */
	public function register(): void {
		add_action( 'admin_menu', array( $this, 'register_page' ) );
		// Render before admin-header.php so other plugins' admin notices never print.
		add_action( 'admin_init', array( $this, 'maybe_render_early' ), 1 );
		add_action( 'wpdude_dc_picking_order_actions', array( self::class, 'render_picking_button' ), 5, 1 );
		add_action( 'wpdude_dc_order_fulfilment_print_actions', array( self::class, 'render_order_detail_button' ), 5, 1 );
	}

	/**
	 * Take over the request before WP admin chrome / notices load.
	 */
	public function maybe_render_early(): void {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- screen routing only.
		$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( (string) $_GET['page'] ) ) : '';
		if ( self::PAGE_SLUG !== $page ) {
			return;
		}
		self::render();
	}

	/**
	 * Hidden admin page (opened from picking / order detail).
	 */
	public function register_page(): void {
		add_submenu_page(
			null,
			__( 'Shipping label', 'dude-commerce' ),
			__( 'Shipping label', 'dude-commerce' ),
			'manage_options',
			self::PAGE_SLUG,
			array( self::class, 'render' )
		);
	}

	/**
	 * Shipping label URL for an order UUID.
	 */
	public static function url( string $uuid, bool $autoprint = false ): string {
		$args = array(
			'page' => self::PAGE_SLUG,
			'uuid' => $uuid,
		);
		if ( $autoprint ) {
			$args['autoprint'] = '1';
		}
		return add_query_arg( $args, admin_url( 'admin.php' ) );
	}

	/**
	 * Button on picking card.
	 *
	 * @param array<string, mixed> $order Order.
	 */
	public static function render_picking_button( array $order ): void {
		self::render_button( $order, 'button wpdude-dc-picking-card__label' );
	}

	/**
	 * Button on order detail Fulfilment section.
	 *
	 * @param array<string, mixed> $order Order.
	 */
	public static function render_order_detail_button( array $order ): void {
		self::render_button( $order, 'button button-hero wpdude-dc-order-fulfilil__print' );
	}

	/**
	 * @param array<string, mixed> $order      Order.
	 * @param string               $css_class Button classes.
	 */
	private static function render_button( array $order, string $css_class ): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$uuid = (string) ( $order['uuid'] ?? '' );
		if ( '' === $uuid ) {
			return;
		}
		?>
		<a class="<?php echo esc_attr( $css_class ); ?>" href="<?php echo esc_url( self::url( $uuid, true ) ); ?>" target="_blank" rel="noopener noreferrer">
			<?php echo esc_html__( 'Print shipping label', 'dude-commerce' ); ?>
		</a>
		<?php
	}

	/**
	 * Render printable HTML and exit.
	 */
	public static function render(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to access this page.', 'dude-commerce' ) );
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only print view; manage_options checked above.
		$uuid = isset( $_GET['uuid'] ) ? sanitize_text_field( wp_unslash( (string) $_GET['uuid'] ) ) : '';
		if ( '' === $uuid ) {
			wp_die( esc_html__( 'Missing order.', 'dude-commerce' ) );
		}

		$order = ( new Order_Repository() )->find_by_uuid( $uuid );
		if ( ! $order ) {
			wp_die( esc_html__( 'Order not found.', 'dude-commerce' ) );
		}

		$shop_name = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
		$lines     = self::address_lines( $order );
		$order_id  = (int) ( $order['id'] ?? 0 );

		wp_register_style(
			'wpdude-dc-shipping-label',
			WPDUDE_DC_URL . 'assets/css/shipping-label.css',
			array(),
			WPDUDE_DC_VERSION
		);
		wp_register_script(
			'wpdude-dc-print-autoprint',
			WPDUDE_DC_URL . 'assets/js/print-autoprint.js',
			array(),
			WPDUDE_DC_VERSION,
			true
		);
		wp_enqueue_style( 'wpdude-dc-shipping-label' );
		wp_enqueue_script( 'wpdude-dc-print-autoprint' );
		?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
	<meta charset="<?php bloginfo( 'charset' ); ?>" />
	<title><?php echo esc_html( sprintf( /* translators: %d: order ID */ __( 'Shipping label — Order #%d', 'dude-commerce' ), $order_id ) ); ?></title>
	<?php wp_print_styles( 'wpdude-dc-shipping-label' ); ?>
</head>
<body>
	<div class="actions">
		<button type="button" id="wpdude-dc-print"><?php echo esc_html__( 'Print', 'dude-commerce' ); ?></button>
		<a href="<?php echo esc_url( Picking_Page::url() ); ?>"><?php echo esc_html__( 'Back to picking', 'dude-commerce' ); ?></a>
	</div>

	<div class="label">
		<p class="from"><?php echo esc_html__( 'From', 'dude-commerce' ); ?></p>
		<p class="shop"><?php echo esc_html( $shop_name ); ?></p>
		<p class="to-label"><?php echo esc_html__( 'Ship to', 'dude-commerce' ); ?></p>
		<p class="address"><?php echo esc_html( ! empty( $lines ) ? implode( "\n", $lines ) : '—' ); ?></p>
		<p class="order-ref">
			<?php
			echo esc_html(
				sprintf(
					/* translators: %d: order post ID */
					__( 'Order #%d', 'dude-commerce' ),
					$order_id
				)
			);
			?>
		</p>
	</div>

	<?php wp_print_scripts( 'wpdude-dc-print-autoprint' ); ?>
</body>
</html>
		<?php
		exit;
	}

	/**
	 * Delivery address lines with country names (no phone/email).
	 *
	 * @param array<string, mixed> $order Order.
	 * @return list<string>
	 */
	private static function address_lines( array $order ): array {
		$shipping = is_array( $order['shipping_address'] ?? null ) ? $order['shipping_address'] : array();
		$lines    = array();

		$name = trim( (string) ( $shipping['name'] ?? $order['customer_name'] ?? '' ) );
		if ( '' !== $name ) {
			$lines[] = $name;
		}

		$address = is_array( $shipping['address'] ?? null ) ? $shipping['address'] : $shipping;
		foreach ( array( 'line1', 'line2', 'city', 'state', 'postal_code' ) as $key ) {
			$val = trim( (string) ( $address[ $key ] ?? '' ) );
			if ( '' !== $val ) {
				$lines[] = $val;
			}
		}

		$country_code = strtoupper( trim( (string) ( $address['country'] ?? '' ) ) );
		if ( '' !== $country_code ) {
			$countries = Countries::all();
			$lines[]   = $countries[ $country_code ] ?? $country_code;
		}

		return $lines;
	}
}
