<?php
/**
 * ScanForm History REST Controller
 *
 * Handles REST API requests for USPS ScanForms History.
 *
 * @package Automattic\WCShipping\ScanForm
 */

namespace Automattic\WCShipping\ScanForm;

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

use Automattic\WCShipping\Connect\WC_Connect_Functions;
use Automattic\WCShipping\WCShippingRESTController;
use Automattic\WooCommerce\Utilities\OrderUtil;
use WP_Error;
use WP_REST_Response;
use WP_REST_Request;

/**
 * ScanForm History REST Controller class.
 */
class ScanFormHistoryRESTController extends WCShippingRESTController {

	/**
	 * ScanForm service.
	 *
	 * @var ScanFormService
	 */
	private ScanFormService $scanform_service;

	/**
	 * Class constructor.
	 *
	 * @param ScanFormService $scanform_service     ScanForm service instance.
	 */
	public function __construct( ScanFormService $scanform_service ) {
		$this->scanform_service = $scanform_service;
	}

	/**
	 * Endpoint namespace.
	 *
	 * @var string
	 */
	protected $rest_base = 'scan-form';

	/**
	 * Register routes for ScanForm endpoints.
	 */
	public function register_routes() {
		// GET /wcshipping/v1/scan-form/history - Get ScanForm history with pagination.
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/history',
			array(
				array(
					'methods'             => 'GET',
					'callback'            => array( $this, 'get_scan_form_history' ),
					'permission_callback' => array( WC_Connect_Functions::class, 'user_can_manage_labels' ),
					'args'                => array(
						'page'     => array(
							'default'           => 1,
							'type'              => 'integer',
							'minimum'           => 1,
							'sanitize_callback' => 'absint',
						),
						'per_page' => array(
							'default'           => 20,
							'type'              => 'integer',
							'minimum'           => 1,
							'maximum'           => 100,
							'sanitize_callback' => 'absint',
						),
					),
				),
			)
		);

		// GET /wcshipping/v1/scan-form/{scan_form_id}/labels - Get labels for a ScanForm.
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/(?P<scan_form_id>[a-zA-Z0-9_]+)/labels',
			array(
				array(
					'methods'             => 'GET',
					'callback'            => array( $this, 'get_scan_form_labels' ),
					'permission_callback' => array( WC_Connect_Functions::class, 'user_can_manage_labels' ),
					'args'                => array(
						'scan_form_id' => array(
							'required'          => true,
							'type'              => 'string',
							'sanitize_callback' => 'sanitize_text_field',
						),
					),
				),
			)
		);
	}

	/**
	 * Get ScanForm history with pagination.
	 *
	 * @param WP_REST_Request $request Request object containing page and per_page parameters.
	 *
	 * @return WP_REST_Response Response with paginated ScanForm history.
	 */
	public function get_scan_form_history( WP_REST_Request $request ): WP_REST_Response {
		$page     = $request->get_param( 'page' ) ?? 1;
		$per_page = $request->get_param( 'per_page' ) ?? 20;
		$offset   = ( $page - 1 ) * $per_page;

		// Get paginated ScanForms directly from database.
		$paginated_result = $this->scanform_service->get_paginated_scan_forms( $per_page, $offset );
		$scan_forms_page  = $paginated_result['scan_forms'];
		$total            = $paginated_result['total'];
		$total_pages      = ceil( $total / $per_page );

		return new WP_REST_Response(
			array(
				'success'     => true,
				'scan_forms'  => $scan_forms_page,
				'total'       => $total,
				'page'        => $page,
				'per_page'    => $per_page,
				'total_pages' => $total_pages,
			),
			200
		);
	}

	/**
	 * Get labels for a specific ScanForm.
	 *
	 * @param WP_REST_Request $request Request object containing scan_form_id.
	 *
	 * @return WP_REST_Response|WP_Error Response with label details or error.
	 */
	public function get_scan_form_labels( WP_REST_Request $request ) {
		$scan_form_id = $request->get_param( 'scan_form_id' );

		// Validate scan_form_id format (alphanumeric and underscores only).
		if ( empty( $scan_form_id ) || ! preg_match( '/^[a-zA-Z0-9_]+$/', $scan_form_id ) ) {
			return new WP_Error(
				'invalid_scan_form_id',
				__( 'Invalid SCAN Form ID format', 'woocommerce-shipping' ),
				array( 'status' => 400 )
			);
		}

		global $wpdb;

		// Get the appropriate table and column names based on HPOS/legacy.
		$meta_table       = OrderUtil::get_table_for_order_meta();
		$meta_join_column = OrderUtil::custom_orders_table_usage_is_enabled() ? 'order_id' : 'post_id';

		// Query all orders that have this scan_form_id in their _wcshipping_scan_forms meta.
		$results = $wpdb->get_results(
			$wpdb->prepare(
				'SELECT %i as order_id, meta_value
				FROM %i
				WHERE meta_key = %s
				ORDER BY %i DESC',
				$meta_join_column,
				$meta_table,
				'_wcshipping_scan_forms',
				$meta_join_column
			)
		);

		// Find the scan form and collect label_ids.
		$label_ids = array();
		$order_ids = array();

		foreach ( $results as $row ) {
			$scan_forms = maybe_unserialize( $row->meta_value );
			if ( empty( $scan_forms ) || ! is_array( $scan_forms ) ) {
				continue;
			}

			foreach ( $scan_forms as $scan_form ) {
				if ( ( $scan_form['scan_form_id'] ?? '' ) === $scan_form_id ) {
					if ( ! empty( $scan_form['label_ids'] ) && is_array( $scan_form['label_ids'] ) ) {
						$label_ids = array_merge( $label_ids, $scan_form['label_ids'] );
					}
					$order_ids[] = (int) $row->order_id;
				}
			}
		}

		if ( empty( $label_ids ) ) {
			return new WP_REST_Response(
				array(
					'success' => true,
					'labels'  => array(),
				),
				200
			);
		}

		// Fetch label and shipment date data for these orders.
		$order_ids    = array_unique( $order_ids );
		$all_labels   = $this->scanform_service->get_order_meta_bulk( $order_ids, 'wcshipping_labels' );
		$all_dates    = $this->scanform_service->get_order_meta_bulk( $order_ids, '_wcshipping_shipment_dates' );
		$orders_cache = array();

		$labels_data = array();

		foreach ( $order_ids as $order_id ) {
			$order_labels = $all_labels[ $order_id ] ?? array();
			if ( empty( $order_labels ) || ! is_array( $order_labels ) ) {
				continue;
			}

			$shipment_dates = $all_dates[ $order_id ] ?? array();

			foreach ( $order_labels as $label ) {
				$label_id = $label['label_id'];

				// Only include labels that are in this ScanForm.
				if ( ! in_array( $label_id, $label_ids, true ) ) {
					continue;
				}

				// Load order object.
				if ( ! isset( $orders_cache[ $order_id ] ) ) {
					$orders_cache[ $order_id ] = wc_get_order( $order_id );
				}

				$order = $orders_cache[ $order_id ];
				if ( ! $order ) {
					continue;
				}

				// Get shipping date for this shipment.
				$shipment_id   = $label['id'];
				$shipment_key  = 'shipment_' . $shipment_id;
				$shipping_date = $shipment_dates[ $shipment_key ]['shipping_date'] ?? '-';

				$labels_data[] = array(
					'label_id'      => $label_id,
					'order_id'      => $order_id,
					'tracking'      => $label['tracking'],
					'created'       => $label['created'],
					'service_name'  => $label['service_name'],
					'order_number'  => $order->get_order_number(),
					'shipping_name' => $order->get_formatted_shipping_full_name(),
					'shipping_date' => $shipping_date,
				);
			}
		}

		return new WP_REST_Response(
			array(
				'success' => true,
				'labels'  => $labels_data,
			),
			200
		);
	}
}