<?php

namespace Simplyin\Simplyin_W_Plugin\Admin;

use Simplyin\Simplyin_W_Plugin\Admin\Template_Components\Select;
use Simplyin\Simplyin_W_Plugin\Shipping_Mapping\Integration\Integration_Interface;
use Simplyin\Simplyin_W_Plugin\Shipping_Mapping\Mapping;
use Simplyin\Simplyin_W_Plugin\Shipping_Mapping\Simplyin\Simplyin_Method_Interface;

class Shipping_Mapping_Options {

	private Mapping $shipping_mapping;

	/**
	 * @var Select[]
	 */
	private static ?array $shipping_mapping_fields = null;


	public function __construct( ?Mapping $mapping = null ) {
		if ( $mapping ) {
			$this->shipping_mapping = $mapping;
		} else {
			$this->shipping_mapping = new Mapping();

		}
	}


	/**
	 * @return Select[]
	 */
	public function get_shipping_mapping_fields( bool $force_regenerate = false
	): array {

		if ( self::$shipping_mapping_fields ) {
			return self::$shipping_mapping_fields;
		}

		$mapping = $this->shipping_mapping;
		$this->shipping_mapping->build_mapping();

		$selects                 = [];
		$integrations_for_widget = [];

		foreach ( $mapping->get_mapping_items() as $mapping_item ) {
			$select = new Select();
			$select->set_option_id( $mapping_item->get_simplyin_method()
			                                     ->get_id() );
			$select_name = $this->build_select_name( $mapping_item->get_simplyin_method() );
			$select->set_name( $select_name );
			$select->set_label( $mapping_item->get_simplyin_method()
			                                 ->get_title() );
			$select->set_multiple( false );
			$options = [];

			foreach ( $mapping_item->get_integrations() as $integration ) {
				$option_key = $this->build_option_key( $integration );
				if ( ! isset( $integrations_for_widget[ $option_key ] ) ) {
					$integrations_for_widget[ $mapping_item
						->get_simplyin_method()
						->get_id() ][ $option_key ] = $integration->to_array();
				}
				$options[ $option_key ] = $integration->get_title();
			}

			if ( empty( $options ) ) {
				continue;
			}

			$options = [
				           'none' => __( 'None',
					           'simplyin' ),
			           ] + $options;

			$value = $this->get_mapping_value( $select_name );
			$select->set_selected_options( $value ? [ $value ] : [] );
			$select->set_available_options( $options );
			$selects[] = $select;
		}

		self::$shipping_mapping_fields = $selects;
		$this->save_integrations( $integrations_for_widget );


		return $selects;
	}


	private function save_integrations( array $integrations_for_widget ) {
		simplyin()->update_option( 'SimplyInShippingIntegrations',
			$integrations_for_widget,
			'shipping_mapping' );
	}

	public function get_mapping_cache(): array {
		$cache = (array) get_option( 'SimplyInShippingMappingCache' );

		return $cache;
	}

	private function rebuild_mapping_cache(
		string $option_id,
		?string $new_value
	): void {
		$cache = (array) get_option( 'SimplyInShippingMappingCache' );
		$cache = array_filter( $cache );

		simplyin()->get_simplyin_logger()->log_if_wpdebug_on(
			sprintf( "[rebuild_mapping_cache] %s",
				wp_json_encode( [
					'new_value' => $new_value,
					'option_id' => $option_id,
				] ),
			),
			'shipping_mapping' );

		if ( ! $new_value ) {

			if ( isset( $cache[ $option_id ] ) ) {
				unset( $cache[ $option_id ] );

			} else {
				return;
			}
		} else {
			$cache[ $option_id ] = $new_value;
		}


		simplyin()->update_option( 'SimplyInShippingMappingCache',
			$cache,
			'shipping_mapping' );
	}

	public function register_settings() {

		foreach ( $this->shipping_mapping->get_available_simplyin_methods() as $simplyin_method ) {
			$simplyin_method_id = $simplyin_method->get_id();
			$option_id          = $this->build_select_name( $simplyin_method );

			register_setting(
				'simply_settings_main',
				$option_id,
				[
					'type'              => 'string',
					'sanitize_callback' => 'sanitize_text_field',
				]
			);

			add_action( sprintf( 'update_option_%s',
				$option_id ),
				function ( $old_value, $new_value ) use (
					$simplyin_method_id,
					$option_id
				) {
					$val = is_string( $new_value ) && '' !== $new_value ? $new_value : null;
					$this->rebuild_mapping_cache( $simplyin_method_id,
						$val );
				},
				10,
				2 );


		}
	}

	public function rebuild_mapping() {
		simplyin()->update_option( 'SimplyInShippingMappingCache',
			[] );

		$shipping_mapping_fields = $this->get_shipping_mapping_fields();

		foreach ( $shipping_mapping_fields as $select ) {
			$option_id = $select->get_option_id();
			$this->rebuild_mapping_cache( $option_id,
				get_option( $select->get_name(), 'none' ) );
		}

	}

	private function get_mapping_value( $option_name ): ?string {
		$result = get_option( $option_name );

		return $result ?: null;
	}

	private function build_option_key( Integration_Interface $integration
	): string {
		return sprintf( '%s_%s',
			$integration->get_method(),
			$integration->get_instance_id() );
	}

	private function build_select_name(
		Simplyin_Method_Interface $simplyin_method
	): string {
		return sprintf( 'simply_%s_mapping',
			$simplyin_method->get_id() );
	}


	public function render_fields( array $args ) {

		simplyin()->locate_template( 'shipping_mapping.php',
			[ 'args' => $args ],
			'src/Admin/partials' );

	}


}
