<?php
/**
 * Mobile/tablet picking workflow (NEW → Shipped).
 *
 * @package WPDudeProducts
 */

declare(strict_types=1);

namespace WPDude\Products\Admin;

use WPDude\Products\Checkout\Payment_Completion_Service;
use WPDude\Products\Orders\Order_Repository;
use WPDude\Products\Orders\Statuses;
use WPDude\Products\Products\Product_Meta;
use WPDude\Products\Products\Stock_Service;

/**
 * Dedicated picking screen: pick details → Ship.
 */
final class Picking_Page {

	public const PAGE_SLUG = 'dude-commerce-picking';

	/**
	 * Register hooks.
	 */
	public function register(): void {
		add_action( 'admin_init', array( $this, 'handle_ship' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
	}

	/**
	 * Picking page URL.
	 *
	 * @param array<string, string> $args Extra query args.
	 */
	public static function url( array $args = array() ): string {
		return add_query_arg(
			array_merge(
				array( 'page' => self::PAGE_SLUG ),
				$args
			),
			admin_url( 'admin.php' )
		);
	}

	/**
	 * Styles for large touch targets.
	 *
	 * @param string $hook Current admin page hook.
	 */
	public function enqueue_assets( string $hook ): void {
		if ( ! isset( $_GET['page'] ) || self::PAGE_SLUG !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}

		wp_enqueue_style(
			'wpdude-dc-picking',
			WPDUDE_DC_URL . 'assets/css/picking.css',
			array(),
			WPDUDE_DC_VERSION
		);

		wp_enqueue_script(
			'wpdude-dc-picking',
			WPDUDE_DC_URL . 'assets/js/picking.js',
			array(),
			WPDUDE_DC_VERSION,
			true
		);
	}

	/**
	 * Ship a NEW order from the picking screen.
	 */
	public function handle_ship(): void {
		if ( empty( $_POST['wpdude_dc_picking_nonce'] ) || empty( $_POST['wpdude_dc_order_uuid'] ) ) {
			return;
		}
		if ( empty( $_POST['wpdude_dc_picking_ship'] ) ) {
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( (string) $_POST['wpdude_dc_picking_nonce'] ) ), 'wpdude_dc_picking_ship' ) ) {
			return;
		}

		$uuid  = sanitize_text_field( wp_unslash( (string) $_POST['wpdude_dc_order_uuid'] ) );
		$repo  = new Order_Repository();
		$order = $repo->find_by_uuid( $uuid );

		$redirect = self::url();

		if ( ! $order ) {
			wp_safe_redirect( add_query_arg( 'wpdude_dc_picking_error', 'not_found', $redirect ) );
			exit;
		}

		if ( Statuses::NEW !== (string) $order['status'] ) {
			wp_safe_redirect( add_query_arg( 'wpdude_dc_picking_error', 'not_new', $redirect ) );
			exit;
		}

		$result = $repo->transition_status( (int) $order['id'], Statuses::SHIPPED );
		if ( is_wp_error( $result ) ) {
			wp_safe_redirect( add_query_arg( 'wpdude_dc_picking_error', 'transition', $redirect ) );
			exit;
		}

		wp_safe_redirect( add_query_arg( 'wpdude_dc_picking_shipped', '1', $redirect ) );
		exit;
	}

	/**
	 * Render picking UI.
	 */
	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' ) );
		}

		$repo   = new Order_Repository();
		$result = $repo->query(
			array(
				'status'   => Statuses::NEW,
				'per_page' => 50,
				'page'     => 1,
			)
		);
		$orders = $result['items'];

		// phpcs:disable WordPress.Security.NonceVerification.Recommended -- admin notices after redirect.
		$shipped = isset( $_GET['wpdude_dc_picking_shipped'] );
		$error   = isset( $_GET['wpdude_dc_picking_error'] ) ? sanitize_key( wp_unslash( (string) $_GET['wpdude_dc_picking_error'] ) ) : '';
		// phpcs:enable WordPress.Security.NonceVerification.Recommended
		?>
		<div class="wrap wpdude-dc-picking">
			<h1><?php echo esc_html__( 'Picking', 'dude-commerce' ); ?></h1>
			<p class="wpdude-dc-picking__intro">
				<?php echo esc_html__( 'Pick the item from stock, then tap Ship when it is ready to leave.', 'dude-commerce' ); ?>
			</p>

			<?php if ( $shipped ) : ?>
				<div class="notice notice-success is-dismissible"><p><?php echo esc_html__( 'Order marked as shipped.', 'dude-commerce' ); ?></p></div>
			<?php endif; ?>
			<?php if ( '' !== $error ) : ?>
				<div class="notice notice-error is-dismissible"><p><?php echo esc_html( self::error_message( $error ) ); ?></p></div>
			<?php endif; ?>

			<?php if ( empty( $orders ) ) : ?>
				<div class="wpdude-dc-picking__empty">
					<p><?php echo esc_html__( 'No new orders to pick right now.', 'dude-commerce' ); ?></p>
					<p>
						<a class="button" href="<?php echo esc_url( Orders_Page::list_url() ); ?>">
							<?php echo esc_html__( 'View all orders', 'dude-commerce' ); ?>
						</a>
					</p>
				</div>
			<?php else : ?>
				<p class="wpdude-dc-picking__count">
					<?php
					echo esc_html(
						sprintf(
							/* translators: %d: number of new orders */
							_n( '%d order to pick', '%d orders to pick', count( $orders ), 'dude-commerce' ),
							count( $orders )
						)
					);
					?>
				</p>
				<div class="wpdude-dc-picking__list">
					<?php foreach ( $orders as $order ) : ?>
						<?php self::render_card( $order ); ?>
					<?php endforeach; ?>
				</div>
			<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * One picking card.
	 *
	 * @param array<string, mixed> $order Order.
	 */
	private static function render_card( array $order ): void {
		$payload  = Payment_Completion_Service::public_success_payload( $order );
		$shipping = is_array( $order['shipping_address'] ?? null ) ? $order['shipping_address'] : array();
		$address  = self::format_address( $shipping, $order );
		$detail   = Orders_Page::list_url( array( 'order' => (string) $order['uuid'] ) );
		$qty      = max( 1, (int) ( $order['qty'] ?? 1 ) );
		$sku      = self::order_sku( $order );
		?>
		<article class="wpdude-dc-picking-card" data-order-uuid="<?php echo esc_attr( (string) $order['uuid'] ); ?>">
			<div class="wpdude-dc-picking-card__qty" aria-label="<?php echo esc_attr__( 'Quantity', 'dude-commerce' ); ?>">
				<span class="wpdude-dc-picking-card__qty-num"><?php echo esc_html( (string) $qty ); ?></span>
				<span class="wpdude-dc-picking-card__qty-label"><?php echo esc_html( _n( 'item', 'items', $qty, 'dude-commerce' ) ); ?></span>
			</div>

			<div class="wpdude-dc-picking-card__body">
				<h2 class="wpdude-dc-picking-card__product"><?php echo esc_html( (string) $payload['product_name'] ); ?></h2>
				<?php if ( '' !== $sku ) : ?>
					<p class="wpdude-dc-picking-card__sku">
						<strong><?php echo esc_html__( 'SKU', 'dude-commerce' ); ?>:</strong>
						<code><?php echo esc_html( $sku ); ?></code>
					</p>
				<?php endif; ?>
				<?php if ( '' !== (string) $payload['options_label'] ) : ?>
					<p class="wpdude-dc-picking-card__options">
						<strong><?php echo esc_html__( 'Options', 'dude-commerce' ); ?>:</strong>
						<?php echo esc_html( (string) $payload['options_label'] ); ?>
					</p>
				<?php endif; ?>

				<p class="wpdude-dc-picking-card__customer">
					<strong><?php echo esc_html__( 'Ship to', 'dude-commerce' ); ?></strong><br />
					<?php echo wp_kses_post( nl2br( esc_html( $address ) ) ); ?>
				</p>

				<p class="wpdude-dc-picking-card__meta">
					<a href="<?php echo esc_url( $detail ); ?>"><?php echo esc_html__( 'Order details', 'dude-commerce' ); ?></a>
					<span class="wpdude-dc-picking-card__uuid"><code><?php echo esc_html( substr( (string) $order['uuid'], 0, 8 ) ); ?>…</code></span>
				</p>
			</div>

			<div class="wpdude-dc-picking-card__actions">
				<?php
				/**
				 * Extra actions on a picking card (e.g. packing slip).
				 *
				 * @param array<string, mixed> $order Order.
				 */
				do_action( 'wpdude_dc_picking_order_actions', $order );
				?>
				<form method="post" class="wpdude-dc-picking-card__ship-form">
					<?php wp_nonce_field( 'wpdude_dc_picking_ship', 'wpdude_dc_picking_nonce' ); ?>
					<input type="hidden" name="wpdude_dc_order_uuid" value="<?php echo esc_attr( (string) $order['uuid'] ); ?>" />
					<button type="button" class="button wpdude-dc-picking-card__pick" data-wpdude-dc-pick>
						<?php echo esc_html__( 'Pick', 'dude-commerce' ); ?>
					</button>
					<button type="submit" name="wpdude_dc_picking_ship" value="1" class="button button-primary wpdude-dc-picking-card__ship" data-wpdude-dc-ship disabled>
						<?php echo esc_html__( 'Ship', 'dude-commerce' ); ?>
					</button>
				</form>
			</div>
		</article>
		<?php
	}

	/**
	 * SKU from order snapshot, or live product/combination lookup.
	 *
	 * @param array<string, mixed> $order Order.
	 */
	private static function order_sku( array $order ): string {
		$line = is_array( $order['line_item'] ?? null ) ? $order['line_item'] : array();
		$sku  = isset( $line['sku'] ) ? Product_Meta::normalize_sku( (string) $line['sku'] ) : '';
		if ( '' !== $sku ) {
			return $sku;
		}
		return Stock_Service::line_sku(
			(int) ( $order['product_id'] ?? 0 ),
			(string) ( $order['combination_key'] ?? '' )
		);
	}

	/**
	 * @param array<string, mixed> $shipping Stripe shipping_details.
	 * @param array<string, mixed> $order    Order row.
	 */
	private static function format_address( array $shipping, array $order ): string {
		$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', 'country' ) as $key ) {
			$val = trim( (string) ( $address[ $key ] ?? '' ) );
			if ( '' !== $val ) {
				$lines[] = $val;
			}
		}

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

		$email = trim( (string) ( $order['customer_email'] ?? '' ) );
		if ( '' !== $email ) {
			$lines[] = $email;
		}

		return ! empty( $lines ) ? implode( "\n", $lines ) : __( 'No delivery address on file.', 'dude-commerce' );
	}

	/**
	 * Human error from redirect code.
	 */
	private static function error_message( string $code ): string {
		$map = array(
			'not_found'  => __( 'Order not found.', 'dude-commerce' ),
			'not_new'    => __( 'That order is no longer a new order.', 'dude-commerce' ),
			'transition' => __( 'Could not mark the order as shipped.', 'dude-commerce' ),
		);
		return $map[ $code ] ?? __( 'Something went wrong.', 'dude-commerce' );
	}
}
