<?php
/**
 * Shared adapter behaviour.
 *
 * @package RewindBrevoFormBridge
 */

namespace RewindBrevoFormBridge\Adapters;

use RewindBrevoFormBridge\Feeds\Processor;

defined( 'ABSPATH' ) || exit;

/**
 * Base class for adapters: hands normalised Submissions to the Feed
 * Processor and centralises the spam skip.
 *
 * @since 0.3.0
 */
abstract class AbstractAdapter implements Adapter {

	/**
	 * Feed processor.
	 *
	 * @var Processor
	 */
	protected Processor $processor;

	/**
	 * Constructor.
	 *
	 * @since 0.3.0
	 * @param Processor $processor The feed processor.
	 */
	public function __construct( Processor $processor ) {
		$this->processor = $processor;
	}

	/**
	 * Normalise a raw payload and, unless it should be skipped, hand it to
	 * the processor. The one path from form plugin to Brevo.
	 *
	 * @since 0.3.0
	 * @param mixed $raw The form plugin's raw payload.
	 * @return void
	 */
	protected function dispatch( $raw ): void {
		$submission = $this->normalize_submission( $raw );

		if ( null === $submission ) {
			return;
		}

		if ( $this->should_skip( $submission ) ) {
			return;
		}

		$this->processor->process( $submission );
	}

	/**
	 * Whether a submission must not be processed at all (e.g. spam).
	 * Adapters flag spam inside the raw payload under '_rbfb_spam'.
	 *
	 * @since 0.3.0
	 * @param Submission $submission The normalised submission.
	 * @return bool
	 */
	protected function should_skip( Submission $submission ): bool {
		$raw = $submission->raw();

		return ! empty( $raw['_rbfb_spam'] );
	}

	/**
	 * Best-effort client IP, honouring reverse proxies is deliberately NOT
	 * attempted (headers are spoofable); REMOTE_ADDR only.
	 *
	 * @since 0.3.0
	 * @return string
	 */
	protected function client_ip(): string {
		$ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';

		return filter_var( $ip, FILTER_VALIDATE_IP ) ? $ip : '';
	}

	/**
	 * Best-effort URL of the page the form was on.
	 *
	 * @since 0.3.0
	 * @return string
	 */
	protected function source_url(): string {
		$referer = wp_get_referer();

		if ( is_string( $referer ) && '' !== $referer ) {
			return esc_url_raw( $referer );
		}

		return '';
	}

	/**
	 * Flatten one composite value into "parent.child" sub-keys alongside a
	 * joined parent value, so both adapters expose the same shape.
	 *
	 * @since 0.3.0
	 * @param array  $fields     Field map being built (by reference).
	 * @param string $parent_key Composite field key, e.g. 'name-1'.
	 * @param array  $parts      child key => scalar value.
	 * @return void
	 */
	protected function flatten_composite( array &$fields, string $parent_key, array $parts ): void {
		$joined = array();

		foreach ( $parts as $child => $value ) {
			if ( is_scalar( $value ) && '' !== trim( (string) $value ) ) {
				$fields[ $parent_key . '.' . $child ] = (string) $value;
				$joined[]                             = (string) $value;
			}
		}

		$fields[ $parent_key ] = implode( ' ', $joined );
	}
}
