<?php
/**
 * Provider-neutral identity data.
 *
 * @package Carticy\Conversions\Domain
 */

declare(strict_types=1);

namespace Carticy\Conversions\Domain;

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

/**
 * Captured identifiers and customer context for later provider formatting.
 */
final class IdentityData {

	/**
	 * Identity fields.
	 *
	 * @var array<string, string|int>
	 */
	private array $fields;

	/**
	 * Constructor.
	 *
	 * @param array<string, mixed> $fields Raw identity fields.
	 */
	public function __construct( array $fields = array() ) {
		$this->fields = $this->normalize( $fields );
	}

	/**
	 * Rebuild from serialized data.
	 *
	 * @param array<string, mixed> $data Serialized identity data.
	 * @return self
	 */
	public static function from_array( array $data ): self {
		return new self( $data );
	}

	/**
	 * Serialize for storage.
	 *
	 * @return array<string, mixed>
	 */
	public function to_array(): array {
		return $this->fields;
	}

	/**
	 * Normalize identity fields.
	 *
	 * @param array<string, mixed> $fields Raw fields.
	 * @return array<string, string|int>
	 */
	private function normalize( array $fields ): array {
		$allowed = array(
			'customer_id',
			'email',
			'phone',
			'first_name',
			'last_name',
			'country',
			'postcode',
			'ip_address',
			'ip_address_mode',
			'user_agent',
			'ga_client_id',
			'ga_session_id',
			'ga_session_captured_at',
			'fbp',
			'fbc',
		);

		$normalized = array();
		foreach ( $allowed as $key ) {
			if ( ! array_key_exists( $key, $fields ) ) {
				continue;
			}

			if ( 'customer_id' === $key ) {
				$value = abs( (int) $fields[ $key ] );
				if ( $value > 0 ) {
					$normalized[ $key ] = $value;
				}
				continue;
			}

			$value = trim( (string) $fields[ $key ] );
			if ( '' === $value ) {
				continue;
			}

			if ( 'ga_client_id' === $key && 1 !== preg_match( '/^\d+\.\d+$/', $value ) ) {
				continue;
			}

			if ( 'ga_session_id' === $key && 1 !== preg_match( '/^\d+$/', $value ) ) {
				continue;
			}

			if ( 'ga_session_captured_at' === $key && false === strtotime( $value . ' UTC' ) ) {
				continue;
			}

			// Meta cookie identifiers have a documented shape; arbitrary
			// strings would later reach CAPI as garbage match keys.
			if ( in_array( $key, array( 'fbp', 'fbc' ), true ) && 1 !== preg_match( '/^fb\.\d+\.\d+\..+/', $value ) ) {
				continue;
			}

			$normalized[ $key ] = substr( $value, 0, 500 );
		}

		return $normalized;
	}
}
