<?php
/**
 * Class AutoShipmentCreator
 *
 * @package DhlPolska\Shipment
 */

namespace DhlPolska\Shipment;

use DhlPolska\Integration\FlexibleShipping\FlexibleShippingIntegration;
use DhlPolska\WooCommerceSettings\WooCommerceDHLPolskaSettings;
use DhlPolskaVendor\Psr\Log\LoggerInterface;
use DhlPolskaVendor\WPDesk\PluginBuilder\Plugin\Hookable;
use Exception;
use WC_Order;

/**
 * Creates DHL shipments automatically on order status change.
 */
class AutoShipmentCreator implements Hookable {

	private WooCommerceDHLPolskaSettings $settings;

	private LoggerInterface $logger;

	public function __construct( WooCommerceDHLPolskaSettings $settings, LoggerInterface $logger ) {
		$this->settings = $settings;
		$this->logger   = $logger;
	}

	/**
	 * @return void
	 */
	public function hooks() {
		add_action( 'woocommerce_order_status_changed', [ $this, 'maybe_create_shipments' ], 10, 4 );
	}

	/**
	 * @param int            $order_id .
	 * @param string         $old_status .
	 * @param string         $new_status .
	 * @param WC_Order|false $order .
	 *
	 * @return void
	 */
	public function maybe_create_shipments( $order_id, $old_status, $new_status, $order ) {
		$auto_statuses = $this->settings->get_auto_shipment_statuses();
		if ( empty( $auto_statuses ) || ! $this->is_target_status( (string) $new_status, $auto_statuses ) ) {
			return;
		}

		if ( ! $order instanceof WC_Order ) {
			$order = wc_get_order( $order_id );
		}

		if ( ! $order || ! function_exists( 'fs_get_order_shipments' ) ) {
			return;
		}

		$shipments = fs_get_order_shipments( $order->get_id(), FlexibleShippingIntegration::INTEGRATION_ID );
		if ( empty( $shipments ) ) {
			return;
		}

		/** @var DhlShipment $shipment */
		foreach ( $shipments as $shipment ) {
			$shipment_data = new ShipmentData( $shipment, $order, $this->settings );
			if ( '' !== $shipment_data->get_shipment_id() ) {
				continue;
			}

			$shipment->set_sent_via_auto();

			try {
				$shipment->api_create();
			} catch ( Exception $exception ) {
				$this->logger->error(
					sprintf(
						'DHL API auto create shipment error (order: %d, shipment: %d): %s',
						$order->get_id(),
						$shipment->get_id(),
						$exception->getMessage()
					)
				);
			}
		}
	}

	/**
	 * @param string   $new_status .
	 * @param string[] $auto_statuses .
	 *
	 * @return bool
	 */
	private function is_target_status( string $new_status, array $auto_statuses ): bool {
		$normalized_new_status = $this->normalize_status( $new_status );

		foreach ( $auto_statuses as $status ) {
			$status = (string) $status;
			if ( $status === $new_status || $status === $normalized_new_status ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * @param string $status .
	 *
	 * @return string
	 */
	private function normalize_status( string $status ): string {
		if ( 0 === strpos( $status, 'wc-' ) ) {
			return $status;
		}

		return 'wc-' . $status;
	}
}
