<?php
/**
 * Option-backed affiliate routing repository.
 *
 * @package Affilun\Application\Affiliate
 */

declare(strict_types=1);

namespace Affilun\Application\Affiliate;

use Affilun\Infrastructure\Persistence\OptionStore;
use InvalidArgumentException;

/**
 * Persists provider-specific routing templates in options.
 */
final class OptionStoreAffiliateRoutingRepository {

	/**
	 * Option key.
	 */
	public const OPTION_KEY = 'affilun_affiliate_routing_templates';

	/**
	 * Supported providers.
	 *
	 * @var list<string>
	 */
	public const PROVIDERS = array( 'amazon', 'rakuten', 'yahoo_shopping', 'mercari' );

	/**
	 * Option payload key for the global routing enable flag.
	 */
	private const ENABLED_KEY = '_enabled';

	/**
	 * Option store.
	 */
	private OptionStore $options;

	/**
	 * @param OptionStore $options Option store.
	 */
	public function __construct( OptionStore $options ) {
		$this->options = $options;
	}

	/**
	 * Load templates keyed by provider.
	 *
	 * @return array<string, AffiliateRoutingTemplate>
	 */
	public function load(): array {
		$stored = $this->options->get( self::OPTION_KEY, array() );
		if ( ! is_array( $stored ) || ! $this->enabled() ) {
			return array();
		}

		$templates = array();
		foreach ( self::PROVIDERS as $provider ) {
			$value = $stored[ $provider ] ?? null;
			if ( ! is_string( $value ) || trim( $value ) === '' ) {
				continue;
			}
			try {
				$templates[ $provider ] = new AffiliateRoutingTemplate( $value );
			} catch ( InvalidArgumentException $unused ) {
				unset( $unused );
			}
		}
		return $templates;
	}

	/**
	 * Save raw template strings. Invalid/empty entries are omitted.
	 *
	 * @param array<string,string> $templates Templates.
	 * @param bool                 $enabled   Whether ASP routing is enabled.
	 */
	public function saveRaw( array $templates, bool $enabled = true ): void {
		$normalized = array(
			self::ENABLED_KEY => $enabled,
		);
		foreach ( self::PROVIDERS as $provider ) {
			$value = isset( $templates[ $provider ] ) ? trim( $templates[ $provider ] ) : '';
			if ( $value === '' ) {
				continue;
			}
			$normalized[ $provider ] = ( new AffiliateRoutingTemplate( $value ) )->template();
		}
		$this->options->update( self::OPTION_KEY, $normalized );
	}

	/**
	 * Load raw template strings for forms.
	 *
	 * @return array<string,string>
	 */
	public function loadRaw(): array {
		$stored = $this->options->get( self::OPTION_KEY, array() );
		if ( ! is_array( $stored ) ) {
			return array();
		}

		$raw = array();
		foreach ( self::PROVIDERS as $provider ) {
			$value            = $stored[ $provider ] ?? null;
			$raw[ $provider ] = is_string( $value ) ? $value : '';
		}
		return $raw;
	}

	/**
	 * Whether ASP routing templates should be applied.
	 */
	public function enabled(): bool {
		$stored = $this->options->get( self::OPTION_KEY, array() );
		if ( ! is_array( $stored ) || ! array_key_exists( self::ENABLED_KEY, $stored ) ) {
			return true;
		}

		$value = $stored[ self::ENABLED_KEY ];
		return ! ( $value === false || $value === 0 || $value === '0' || $value === '' || $value === null );
	}
}
