<?php

namespace Formatrica\Capability\Rules;

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

use Formatrica\Capability\Capabilities;
use Formatrica\Capability\Premium_Config_Rule_Interface;

/**
 * Save-path gate for per-field custom HTML attributes (fields.custom_attrs).
 *
 * Reverts a field's attrs map to its saved value on Free (preserve-existing by
 * stable key); a fresh form drops the slot entirely. The output allowlist lives
 * in the sanitizer + renderer (CORE), so grandfathered attrs keep rendering.
 */
final class Custom_Field_Attrs_Rule implements Premium_Config_Rule_Interface
{
    public function capability(): string
    {
        return Capabilities::FIELDS_CUSTOM_ATTRS;
    }

    public function enforce(array &$config, array $existing): array
    {
        $rejected = [];

        if (!isset($config['fields']) || !is_array($config['fields'])) {
            return $rejected;
        }

        $existing_by_key = [];
        foreach (($existing['fields'] ?? []) as $ef) {
            if (is_array($ef) && isset($ef['key']) && is_string($ef['key'])) {
                $existing_by_key[$ef['key']] = $ef;
            }
        }

        foreach ($config['fields'] as $i => $field) {
            if (!is_array($field)) {
                continue;
            }

            $incoming_attrs = self::normalize($field['attrs'] ?? null);
            $field_key = $field['key'] ?? null;
            $existing_attrs = [];
            if ($field_key !== null && isset($existing_by_key[$field_key])) {
                $existing_attrs = self::normalize($existing_by_key[$field_key]['attrs'] ?? null);
            }

            if ($incoming_attrs === $existing_attrs) {
                continue;
            }

            // Revert to the saved map; on a fresh form drop the slot entirely.
            if ($existing_attrs === []) {
                unset($config['fields'][$i]['attrs']);
            } else {
                $config['fields'][$i]['attrs'] = $existing_attrs;
            }

            $rejected[] = [
                'key' => 'fields[' . $i . '].attrs',
                'reason' => __('Custom field attributes are a Pro feature; reverted.', 'formatrica'),
                'capability' => $this->capability(),
                'feature' => 'custom_field_attrs',
            ];
        }

        return $rejected;
    }

    /**
     * @param mixed $value
     * @return array<string, string>
     */
    private static function normalize($value): array
    {
        if (!is_array($value)) {
            return [];
        }
        $out = [];
        foreach ($value as $name => $val) {
            if (!is_string($name) || $name === '') {
                continue;
            }
            $out[$name] = (string) (is_scalar($val) ? $val : '');
        }
        ksort($out);
        return $out;
    }
}
