<?php
/**
 * Hook handler for order creation with Simply.IN.
 *
 * Handles createOrderAndAccount and createOrderWithoutAccount.
 * Resolves Tax ID (NIP) for firm address registration.
 *
 * @package Simplyin\Simplyin_W_Plugin\Hooks
 */

namespace Simplyin\Simplyin_W_Plugin\Hooks;

use Simplyin\Simplyin_W_Plugin\Service\Order\Order_Data_Handler;
use Simplyin\Simplyin_W_Plugin\Service\Order\Tax_Id_Resolver;
use Simplyin\Simplyin_W_Plugin\Sync\SimplyIn_Api_Order_Response;
use WC_Order;

class simplyInOnOrderCreate {

	public function run( WC_Order $order ) {

		$plugin_version      = SimplyInGetPluginVersion();
		$woocommerce_version = get_option( 'woocommerce_version' );

		$payment_method_data = SimplyInGetPaymentMethodData( $order );

		$simplyin_phone_number      = SimplyInGetSanitizedPostData( 'simplyin-phone' ) ?: SimplyInGetSanitizedPostData( 'phoneAppInputField' ) ?: (string) $order->get_meta( '_phoneAppInputField', true );
		$simplyin_phone_prefix      = SimplyInGetSanitizedPostData( 'simplyin-phone-prefix' ) ?: SimplyInGetSanitizedPostData( 'phoneAppInputPrefix' ) ?: (string) $order->get_meta( '_phoneAppInputPrefix', true );
		$simplyin_Token_Input_Value = simplyin()
			->get_simplyin_session()
			->get( 'simplyin_auth_token', '' );
		$create_new_accountVal      = SimplyInGetSanitizedPostData( 'simply-save-checkbox' ) ?: (string) $order->get_meta( '_simply-save-checkbox', true );
		$parcel_machine_id          = SimplyInGetSanitizedPostDataParcelMachineId();
		$parcel_provider_name       = '';
		$simply_billing_id          = SimplyInGetSanitizedPostData( 'simply_billing_id' );
		$simply_shipping_id         = SimplyInGetSanitizedPostData( 'simply_shipping_id' );

		$tax_id = ( new Tax_Id_Resolver() )->resolve( $order );

		$simplyin_session = simplyin()->get_simplyin_session();
		if ( empty( $create_new_accountVal ) ) {
			// Fallback recovery from the WC session: the checkbox lives in the WooCommerce
			// order-review/#payment fragment, which WC re-renders on every updated_checkout,
			// so the POST field can be silently dropped between check and submit. The intent
			// is mirrored to the session on every toggle (see save_create_account_flag AJAX),
			// so when POST/meta are empty the session still carries the shopper's choice.
			$create_new_accountVal = (string) $simplyin_session->get( 'simplyin_create_account', '' );
		}
		if ( empty( $simply_billing_id ) ) {
			$simply_billing_id = (string) $simplyin_session->get( 'simplyin_billing', '' );
		}
		if ( empty( $simply_shipping_id ) ) {
			$simply_shipping_id = (string) $simplyin_session->get( 'simplyin_shipping', '' );
		}
		if ( empty( $parcel_machine_id ) ) {
			$parcel_machine_id = (string) $simplyin_session->get( 'simplyin_parcel_locker_id', '' );
			if ( empty( $parcel_machine_id ) ) {
				$parcel_machine_id = (string) $simplyin_session->get( 'simplyin_parcel', '' );
			}
		}
		$parcel_provider_name = (string) $simplyin_session->get( 'simplyin_parcel_provider', '' );

		$locale        = get_locale();
		$language_code = strtoupper( substr( $locale, 0, 2 ) );

		$full_phone_number = trim( $simplyin_phone_prefix . ' ' . $simplyin_phone_number );

		// The widget phone lives in the same WC-re-rendered #payment fragment as the
		// create-account checkbox and can be dropped before submit. Account creation requires a
		// valid mobile (the backend rejects an empty phoneNumber), so when the widget phone is
		// missing fall back to the WooCommerce billing phone the shopper entered — the same
		// source the payment models use — normalised with the billing country's dial code when
		// it has no leading '+'.
		if ( '' === trim( $simplyin_phone_number ) ) {
			$billing_phone = trim( (string) $order->get_billing_phone() );
			if ( '' !== $billing_phone ) {
				if ( 0 === strpos( $billing_phone, '+' ) ) {
					$full_phone_number = $billing_phone;
				} elseif ( 0 === strpos( $billing_phone, '00' ) ) {
					// "00" is the international call prefix — already country-qualified.
					// preg_replace() returns null on a PCRE error — keep the raw number then
					// rather than sending an empty phone.
					$full_phone_number = preg_replace( '/^00/', '+', $billing_phone ) ?? $billing_phone;
				} else {
					$dial_code         = $this->dial_code_for_country( (string) $order->get_billing_country() );
					$full_phone_number = '' !== $dial_code ? trim( $dial_code . ' ' . $billing_phone ) : $billing_phone;
				}
			}
		}

		$handler_params = [
			'payment_method_data'   => $payment_method_data,
			'plugin_version'        => $plugin_version,
			'woocommerce_version'   => $woocommerce_version,
			'tax_id'                => $tax_id,
			'language_code'         => $language_code,
			'parcel_machine_id'     => $parcel_machine_id,
			'parcel_provider_name'  => $parcel_provider_name,
			'phone_app_input_field' => $full_phone_number,
			'simply_billing_id'     => $simply_billing_id,
			'simply_shipping_id'    => $simply_shipping_id,
		];

		$handler = new Order_Data_Handler();

		simplyin()
			->get_simplyin_logger()
			->log_if_wpdebug_on( sprintf( "[simplyInOnOrderCreate] [run] [request fields: %s]",
				wp_json_encode( [
					'prefix'                     => $simplyin_phone_prefix,
					'phoneAppInputField'         => $full_phone_number,
					'simplyin_Token_Input_Value' => $simplyin_Token_Input_Value,
					'create_new_accountVal'      => $create_new_accountVal,
					'parcel_machine_id'          => $parcel_machine_id,
					'simply_billing_id'          => $simply_billing_id,
					'simply_shipping_id'         => $simply_shipping_id,
					'tax_id'                     => $tax_id,
					'locale'                     => $locale,
					'language_code'              => $language_code,
				] )

			),
				"api-call" );

		$api           = simplyin()->get_api();
		$merchantToken = get_option( 'simplyin_api_key' );


		if ( SimplyInShouldCreateNewAccount( $create_new_accountVal,
			$simplyin_Token_Input_Value ) ) {

			$body_data = $handler->build_create_order_and_account_payload( $order, $handler_params );


			$response = $api->sendRequest(
				'checkout/createOrderAndAccount',
				'POST',
				$body_data
			);

			if ( $response && isset( $response->authToken ) && ! empty( $response->authToken ) ) {
				$order->update_meta_data( '_simplyin_registration_auth_token', $response->authToken );
				$order->save_meta_data();
				simplyin()
					->get_simplyin_logger()
					->log_if_wpdebug_on( sprintf( "[simplyInOnOrderCreate] [createOrderAndAccount] [authToken saved to order meta] [order_id: %s]",
						$order->get_id() ),
						"api-call" );
			}

			$created_order = null;
			if ( isset( $response->createdOrder ) ) {
				$created_order = $response->createdOrder;
			} elseif ( isset( $response->data ) && isset( $response->data->shopOrderNumber ) ) {
				$created_order = $response->data;
			}

			if ( $created_order && SimplyIn_Api_Order_Response::created_order_payload_is_for_this_wc_order( $created_order,
				$order ) ) {
				$this->persist_simplyin_export_meta( $order, (string) $created_order->_id );
			} elseif ( SimplyIn_Api_Order_Response::response_indicates_order_already_exists( $response ) ) {
				$this->mark_simplyin_exported_without_duplicate_api_retry( $order );
			}
		} elseif ( SimplyInHasAuthToken( $simplyin_Token_Input_Value ) ) {
			$body_data = $handler->build_create_order_without_account_payload( $order, $handler_params );

			$response = $api->sendRequest(
				'checkout/createOrderWithoutAccount',
				'POST',
				$body_data,
				[ 'api_token' => urlencode( $simplyin_Token_Input_Value ) ]
			);

			if ( $response && isset( $response->createdOrder )
				&& SimplyIn_Api_Order_Response::created_order_payload_is_for_this_wc_order( $response->createdOrder,
					$order ) ) {
				$this->persist_simplyin_export_meta( $order, (string) $response->createdOrder->_id );
			} elseif ( SimplyIn_Api_Order_Response::response_indicates_order_already_exists( $response ) ) {
				$this->mark_simplyin_exported_without_duplicate_api_retry( $order );
			}

			//			$order_email   = $order->get_billing_email();
			//			$shopOrderNumber = $order->get_order_number();
			//			$merchantToken = get_option( 'simplyin_api_key' );
			//			$newOrderStatus = 'InTransit';
			//
			//			$new_body_data = [
			//				'email'           => $order_email,
			//				'shopOrderNumber' => $shopOrderNumber,
			//				"newOrderStatus" => $newOrderStatus,
			//				"apiKey" => $merchantToken,
			//				'trackings'       => [
			//					[
			//						'number'   => '55555',
			//					],
			//				],
			//			];
			//
			//			$plaintext = json_encode($new_body_data,JSON_UNESCAPED_SLASHES);
			//
			//			$key           = simplyinGetSecretKey($order_email);
			//			$encryptedData = simplyinEncrypt($plaintext, $key);
			//			$hashedEmail   = simplyinHashEmail($order_email);
			//			$orderData = [];
			//			$orderData['encryptedOrderStatusChangeContent'] = $encryptedData;
			//			$orderData['hashedEmail'] = $hashedEmail;
			//
			//			$secondResponse = json_encode(
			//				sendPostRequest(
			//					$orderData,
			//					'encryption/saveEncryptedOrderStatusChange',
			//					$merchantToken
			//				)
			//			);
			//			if ($secondResponse && isset($secondResponse->success) && $secondResponse->success == true) {
			//				$order->update_meta_data('SecondRequestDone', 1);
			//				$order->save_meta_data();
			//			} else {
			//				error_log('Encrypted tracking update failed: ' . print_r($secondResponse, true));
			//			}
		}
	}

	/**
	 * Resolve the international dial code (e.g. "+48") for a WooCommerce billing country code,
	 * using the same countries.json the widget's phone-prefix selector is built from.
	 */
	private function dial_code_for_country( string $country_code ): string {
		static $dial_codes = null;

		$country_code = strtoupper( trim( $country_code ) );
		if ( '' === $country_code ) {
			return '';
		}

		if ( null === $dial_codes ) {
			// Build the code -> dial_code map once per request (O(1) lookups afterwards).
			$dial_codes = [];
			$path       = simplyin()->get_plugin_dir() . 'public/widget/json/countries.json';
			if ( is_readable( $path ) ) {
				$countries = json_decode( (string) file_get_contents( $path ), true );
				if ( is_array( $countries ) ) {
					foreach ( $countries as $country ) {
						if ( isset( $country['code'], $country['dial_code'] ) ) {
							$dial_codes[ strtoupper( (string) $country['code'] ) ] = (string) $country['dial_code'];
						}
					}
				}
			}
		}

		return $dial_codes[ $country_code ] ?? '';
	}

	private function persist_simplyin_export_meta( WC_Order $order, string $simplyin_order_id ): void {
		$order->update_meta_data( 'SimplyInOrderId', $simplyin_order_id );
		$order->update_meta_data( 'SimplyInOrderExported', 1 );
		$order->save_meta_data();
	}

	/**
	 * Stops background sync from re-calling createOrder when checkout already created the order (duplicate request / idempotent API).
	 */
	private function mark_simplyin_exported_without_duplicate_api_retry( WC_Order $order ): void {
		if ( 1 === (int) $order->get_meta( 'SimplyInOrderExported', true ) ) {
			return;
		}
		$order->update_meta_data( 'SimplyInOrderExported', 1 );
		$order->save_meta_data();
	}
}

