<?php
/**
 * Persisted merchant resolutions for detected foreign tags.
 *
 * @package Carticy\Conversions\Diagnostics
 */

declare(strict_types=1);

namespace Carticy\Conversions\Diagnostics;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Stores the merchant's attach/replace/keep-both decision per detected foreign
 * tag so an acknowledged duplicate does not re-raise the duplicate-pixel
 * warning on every Home load. Resolutions are keyed by tag type + id; they are
 * advisory state for the UI and never alter the tracking engine.
 */
final class DetectionResolutions {

	/**
	 * Option storing the resolution map.
	 */
	public const OPTION_NAME = 'carticy_conversions_detection_resolutions';

	/**
	 * Actions a merchant may record for a detected tag.
	 */
	private const ACTIONS = array( 'attach', 'replace', 'keep_both' );

	/**
	 * Read all stored resolutions.
	 *
	 * @return array<int, array<string, string>>
	 */
	public function all(): array {
		$stored = get_option( self::OPTION_NAME, array() );
		if ( ! is_array( $stored ) ) {
			return array();
		}

		$out = array();
		foreach ( $stored as $key => $row ) {
			if ( ! is_array( $row ) ) {
				continue;
			}
			$out[] = array(
				'key'        => (string) $key,
				'type'       => (string) ( $row['type'] ?? '' ),
				'id'         => (string) ( $row['id'] ?? '' ),
				'action'     => (string) ( $row['action'] ?? '' ),
				'resolvedAt' => (string) ( $row['resolved_at'] ?? '' ),
			);
		}

		return $out;
	}

	/**
	 * The stored resolution action for a tag, or '' when unresolved.
	 *
	 * @param string $type Tag type.
	 * @param string $id Tag id.
	 * @return string
	 */
	public function action_for( string $type, string $id ): string {
		$stored = get_option( self::OPTION_NAME, array() );
		if ( ! is_array( $stored ) ) {
			return '';
		}

		$row = $stored[ $this->key( $type, $id ) ] ?? null;

		return is_array( $row ) ? (string) ( $row['action'] ?? '' ) : '';
	}

	/**
	 * Persist a batch of resolutions, returning the applied list.
	 *
	 * @param array<int, array<string, mixed>> $resolutions Raw resolutions.
	 * @return array<int, array<string, string>>
	 */
	public function apply( array $resolutions ): array {
		$stored = get_option( self::OPTION_NAME, array() );
		$stored = is_array( $stored ) ? $stored : array();

		foreach ( $resolutions as $row ) {
			if ( ! is_array( $row ) ) {
				continue;
			}

			$type   = sanitize_key( (string) ( $row['type'] ?? '' ) );
			$id     = sanitize_text_field( (string) ( $row['id'] ?? '' ) );
			$action = sanitize_key( (string) ( $row['action'] ?? '' ) );
			if ( '' === $type || ! in_array( $action, self::ACTIONS, true ) ) {
				continue;
			}

			$stored[ $this->key( $type, $id ) ] = array(
				'type'        => $type,
				'id'          => strtoupper( $id ),
				'action'      => $action,
				'resolved_at' => gmdate( 'Y-m-d H:i:s' ),
			);
		}

		update_option( self::OPTION_NAME, $stored );

		return $this->all();
	}

	/**
	 * Build the stable resolution key for a tag.
	 *
	 * @param string $type Tag type.
	 * @param string $id Tag id.
	 * @return string
	 */
	private function key( string $type, string $id ): string {
		return sanitize_key( $type ) . '|' . strtoupper( trim( $id ) );
	}
}
