<?php

namespace Simplyin\Simplyin_W_Plugin\Payments\Mappers;

use Simplyin\Simplyin_W_Plugin\Lib\Remote\SimplyInApi\Model\PaymentsGetAvailablePaymentMethods200ResponseInner as AvailablePaymentMethod;
use Simplyin\Simplyin_W_Plugin\Payments\Gateway\Model\Order_Data;
use Simplyin\Simplyin_W_Plugin\Payments\Gateway\Model\Payment_Method;
use Simplyin\Simplyin_W_Plugin\Payments\Gateway\Model\Payment_Type_Add_Card;
use Simplyin\Simplyin_W_Plugin\Payments\Gateway\Model\Payment_Type_Blik;
use Simplyin\Simplyin_W_Plugin\Payments\Gateway\Model\Payment_Type_Card;
use Simplyin\Simplyin_W_Plugin\Payments\Gateway\Model\Payment_Type_Default;
use WC_Order;

class Payment_Method_Mapper {

	/** @var array<string,true> types already logged this request — prevents log flooding */
	private static array $logged_unknown_types = [];

	public static function reset_logged_types(): void {
		self::$logged_unknown_types = [];
	}

	public static function map_from_simplyin_api( array $methods_desaralised
	): array {

		$result = [];


		foreach ( $methods_desaralised as $raw_channel ) {
			$provider_raw = $raw_channel->getPaymentProvider();


			switch ( $raw_channel->getType() ) {
				case 'blik':

					$result[] = new Payment_Type_Blik(
						$raw_channel->getPaymentMethodId(),
						$raw_channel->getSlug(),
						$raw_channel->getName(),
						$raw_channel->getType(),
						$raw_channel->getLogoThumbnailUrl(),
						$provider_raw->getId(),
						$provider_raw->getName(),
						$provider_raw->getLogoUrl()
					);
					break;
				case 'card':
					$result[] = new Payment_Type_Card(
						$raw_channel->getPaymentMethodId(),
						$raw_channel->getSlug(),
						$raw_channel->getName(),
						$raw_channel->getType(),
						$raw_channel->getLogoThumbnailUrl(),
						$provider_raw->getId(),
						$provider_raw->getName(),
						$provider_raw->getLogoUrl()
					);
					break;
				case 'add_card':
					$result[] = new Payment_Type_Add_Card(
						$raw_channel->getPaymentMethodId(),
						$raw_channel->getSlug(),
						$raw_channel->getName(),
						$raw_channel->getType(),
						$raw_channel->getLogoThumbnailUrl(),
						$provider_raw->getId(),
						$provider_raw->getName(),
						$provider_raw->getLogoUrl()
					);
					break;
				default:
					$payment_type = is_object( $raw_channel ) && method_exists( $raw_channel, 'getType' )
						? (string) $raw_channel->getType()
						: 'unknown';
					if ( ! isset( self::$logged_unknown_types[ $payment_type ] ) ) {
						self::$logged_unknown_types[ $payment_type ] = true;
						if ( function_exists( 'simplyin' ) ) {
							simplyin()->get_woocommerce_logger( 'payment-methods' )->log_warning(
								sprintf(
									'Simply.IN: unsupported payment type "%s" received from API — skipped.',
									esc_html( $payment_type )
								)
							);
						}
					}
					continue 2;
			}


		}
		$result = self::sort_methods_for_checkout($result);

		return $result;
	}


	/**
	 * @param Payment_Method[] $methods
	 * @return Payment_Method[]
	 */
	private static function sort_methods_for_checkout(array $methods): array
	{
		$type_priority_map = ['card' => 0, 'add_card' => 1];

		usort(
			$methods,
			static function (Payment_Method $left, Payment_Method $right) use ($type_priority_map): int {
				$left_weight  = $type_priority_map[$left->get_type()]  ?? 100;
				$right_weight = $type_priority_map[$right->get_type()] ?? 100;

				if ($left_weight === $right_weight) {
					return 0;
				}
				return $left_weight <=> $right_weight;
			}
		);

		return $methods;
	}


	/**
	 * @param string $serialised
	 *
	 * @return Payment_Method[]
	 */
	public static function deserialize( string $serialised
	): array {
		$allowed = [
			Payment_Method::class,
			Payment_Type_Blik::class,
			Payment_Type_Card::class,
			Payment_Type_Add_Card::class,
			Payment_Type_Default::class,
		];
		$data    = unserialize( $serialised, [ 'allowed_classes' => $allowed ] );

		return $data;
	}

	public static function deserialize_single( string $serialised
	): Payment_Method {

		if ( empty( $serialised ) || ! is_string( $serialised ) ) {
			throw new \UnexpectedValueException( 'Empty serialized payment method data' );
		}

		$allowed = [
			Payment_Method::class,
			Payment_Type_Blik::class,
			Payment_Type_Card::class,
			Payment_Type_Add_Card::class,
			Payment_Type_Default::class,
		];
		$data    = @unserialize( $serialised, [ 'allowed_classes' => $allowed ] );

		if ( $data instanceof Payment_Method ) {
			return $data;
		}

		throw new \UnexpectedValueException( 'Invalid serialized payment method data' );
	}
}
