<?php

namespace Simplyin\Simplyin_W_Plugin;

use WC_Order;

class Tracking_Numbers {


	public function find_tracking_numbers( WC_Order $order ): array {
		$tracking_numbers = $this->get_tracking_numbers_meta( $order );
		$log              = simplyin()
			->get_simplyin_logger();

		if ( empty( $tracking_numbers ) ) {
			$log->log_if_wpdebug_on( sprintf( "[Tracking_Numbers] [find_tracking_numbers] Not found. Now search for InPost numbers [%s]",
				wp_json_encode( [
					'order_id' => $order->get_id(),
				] )

			) );
			$tracking_numbers = $this->find_other_tracking_numbers( $order );

			if ( ! empty( $tracking_numbers ) ) {
				$this->update_tracking_numbers_meta( $tracking_numbers,
					$order );
			}
		}


		$log->log_if_wpdebug_on( sprintf( "[Tracking_Numbers] [find_tracking_numbers] [%s]",
			wp_json_encode( [
				'result'   => $tracking_numbers,
				'order_id' => $order->get_id(),
			] )

		) );

		return $tracking_numbers;
	}

	private function build_tracking_numbers_collection(
		array $tracking_numbers,
		string $provider
	): array {
		$tracking_numbers = array_values( array_unique( $tracking_numbers,
			SORT_REGULAR ) );

		return array_map( function ( $tracking_number ) use (
			$provider
		) {
			return [ 'number' => $tracking_number, 'provider' => $provider ];
		}, $tracking_numbers );
	}

	private function update_tracking_numbers_meta(
		array $tracking_numbers,
		WC_Order $order
	) {
		$order->update_meta_data( '_simplyin_tracking_numbers',
			$tracking_numbers );
		$order->save_meta_data();

		simplyin()
			->get_simplyin_logger()
			->log_if_wpdebug_on( sprintf( "[Tracking_Numbers] [update_tracking_numbers_meta] [%s]",
				wp_json_encode( [
					'result'   => $tracking_numbers,
					'order_id' => $order->get_id(),
				] )

			) );
	}

	public function update_tracking_numbers(
		array $tracking_numbers,
		string $provider,
		WC_Order $order
	) {

		$tracking_numbers_collection = $this->build_tracking_numbers_collection(
			$tracking_numbers,
			$provider
		);

		$this->update_tracking_numbers_meta( $tracking_numbers_collection,
			$order );


	}

	private function get_tracking_numbers_meta(
		WC_Order $order
	): array {
		$found = $order->get_meta( '_simplyin_tracking_numbers' );

		if ( is_array( $found ) && ! empty( $found ) ) {
			return $found;
		}

		return [];
	}

	private function find_other_tracking_numbers( WC_Order $order ): array {
		$id  = $order->get_id();
		$log = simplyin()
			->get_simplyin_logger();

		$log->log_if_wpdebug_on( sprintf( "[Tracking_Numbers] [find_inpost_tracking_numbers] [%s]",
			wp_json_encode( [
				'collect:start #' => $id,
			] )

		) );

		$found = [];

		if ( $raw = $order->get_meta( '_shipx_shipment_object', true ) ) {

			$shipment = is_object( $raw )
				? $raw
				: @unserialize( $raw, [ 'allowed_classes' => true ] );

			if ( $shipment && is_object( $shipment ) ) {

				$internal   = null;
				$gettersInt = [ 'get_internal_data', 'getInternalData' ];
				foreach ( $gettersInt as $g ) {
					if ( method_exists( $shipment, $g ) ) {
						$internal = $shipment->$g();
						break;
					}
				}
				$internal ??= $shipment->internal_data ?? null;

				if ( $internal && is_object( $internal ) ) {
					foreach (
						[
							'get_tracking_number',
							'getTrackingNumber',
						] as $g
					) {
						if ( method_exists( $internal, $g ) ) {
							$tn = $internal->$g();
							break;
						}
					}
					$tn ??= $internal->tracking_number ?? null;

					if ( is_string( $tn ) && preg_match( '/^[0-9A-Z]{10,30}$/',
							$tn ) ) {
						$found[] = [ 'number' => $tn, 'provider' => 'inpost' ];

						$log->log_if_wpdebug_on( sprintf( "[Tracking_Numbers] [find_inpost_tracking_numbers] [%s]",
							wp_json_encode( [
								'collect:found shipx' => $tn,
							] )

						) );
					}
				}
			}
		}

		foreach ( $order->get_items( 'shipping' ) as $item ) {
			foreach (
				[
					'_paczkomat_shipment_id',
					'_paczkomat_tracking_number',
				] as $key
			) {
				if ( $tn = $item->get_meta( $key, true ) ) {
					if ( preg_match( '/^[0-9A-Z]{10,30}$/', $tn ) ) {
						$found[] = [ 'number' => $tn, 'provider' => 'inpost' ];

						$log->log_if_wpdebug_on( sprintf( "[Tracking_Numbers] [find_inpost_tracking_numbers] [%s]",
							wp_json_encode( [
								'collect:found paczkomat' => $tn,
							] ) ) );
					}
				}
			}
		}

		if ( $items = $order->get_meta( '_wc_shipment_tracking_items',
			true ) ) {
			foreach ( (array) $items as $i ) {
				if ( ! empty( $i['tracking_number'] ) && preg_match( '/^[0-9A-Z]{10,30}$/',
						$i['tracking_number'] ) ) {
					$found[] = [
						'number'   => $i['tracking_number'],
						'provider' => $i['carrier_slug'] ?? '',
					];

					$log->log_if_wpdebug_on( sprintf( "[Tracking_Numbers] [find_inpost_tracking_numbers] [%s]",
						wp_json_encode( [
							'collect:found wc_ship' => $i['tracking_number'],
						] ) ) );

				}
			}
		}

		$found = array_values( array_unique( $found, SORT_REGULAR ) );

		$log->log_if_wpdebug_on( sprintf( "[Tracking_Numbers] [find_inpost_tracking_numbers] [%s]",
			wp_json_encode( [
				'collect:result' => $found,
			] ) ) );

		return $found;
	}


}
