<?php
/**
 * Door 3 registration helpers for B9 element style abilities.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks;

use LolaCoreForBricks\Handlers\ElementStyleHandler;
use LolaCoreForBricks\Support\AbilityI18n;

/**
 * Registers element style abilities on the WordPress Abilities API.
 */
final class ElementStyleWpRegistrar
{
    public function registerAbilities(WPAbilitiesRegistrar $registrar): void
    {
        if (!function_exists('wp_register_ability')) {
            return;
        }

        foreach (ElementStyleAbilityMap::entries() as $actionId => $entry) {
            $registrar->registerMappedWriteAbility(
                $entry['slug'],
                AbilityI18n::label($actionId),
                AbilityI18n::description($actionId),
                $this->inputSchema($actionId),
                $this->outputSchema($actionId),
                [$this, $this->callbackMethod($actionId)],
                $entry['destructive'],
                $entry['idempotent']
            );
        }
    }

    /**
     * @param array<string, mixed> $input
     * @return array<string, mixed>
     */
    public function executeStyleElement(array $input): array
    {
        return $this->dispatch('styleElement', $input);
    }

    /**
     * @param array<string, mixed> $input
     * @return array<string, mixed>
     */
    public function executeApplyClasses(array $input): array
    {
        return $this->dispatch('applyClasses', $input);
    }

    /**
     * @param array<string, mixed> $input
     * @return array<string, mixed>
     */
    public function executeRemoveClasses(array $input): array
    {
        return $this->dispatch('removeClasses', $input);
    }

    /**
     * @param array<string, mixed> $input
     * @return array<string, mixed>
     */
    public function executeUpdateElementSettings(array $input): array
    {
        return $this->dispatch('updateElementSettings', $input);
    }

    /**
     * @param array<string, mixed> $input
     * @return array<string, mixed>
     */
    private function dispatch(string $method, array $input): array
    {
        return (new ElementStyleHandler())->{$method}($input, (bool) ($input['dry_run'] ?? false));
    }

    private function callbackMethod(string $actionId): string
    {
        return match ($actionId) {
            'style_element'           => 'executeStyleElement',
            'apply_classes'           => 'executeApplyClasses',
            'remove_classes'          => 'executeRemoveClasses',
            'update_element_settings' => 'executeUpdateElementSettings',
            default                   => 'executeStyleElement',
        };
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function inputSchema(string $actionId): array
    {
        $page   = [
            'post_id' => ['type' => 'integer'],
            'area'    => ['type' => 'string'],
        ];
        $dryRun = ['dry_run' => ['type' => 'boolean']];

        return match ($actionId) {
            'style_element' => array_merge($dryRun, $page, [
                'element_id' => ['type' => 'string'],
                'styles'     => ['type' => 'object'],
                'breakpoint' => ['type' => 'string'],
                'state'      => ['type' => 'string'],
            ]),
            'apply_classes', 'remove_classes' => array_merge($dryRun, $page, [
                'element_ids' => ['type' => 'array', 'items' => ['type' => 'string']],
                'classes'     => ['type' => 'array', 'items' => ['type' => 'string']],
            ]),
            'update_element_settings' => array_merge($dryRun, $page, [
                'element_id' => ['type' => 'string'],
                'settings'   => ['type' => 'object'],
            ]),
            default => $dryRun,
        };
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function outputSchema(string $actionId): array
    {
        unset($actionId);

        return [
            'success'          => ['type' => 'boolean'],
            'message'          => ['type' => 'string'],
            'post_id'          => ['type' => 'integer'],
            'area'             => ['type' => 'string'],
            'element_ids'      => ['type' => 'array'],
            'vocabulary_notes' => ['type' => 'array'],
            'impact'           => ['type' => 'object'],
            'valid_keys'       => ['type' => 'array'],
        ];
    }
}
