<?php
/**
 * Door 3 registration helpers for B10 content shortcut abilities.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks;

use LolaCoreForBricks\Handlers\ContentShortcutHandler;
use LolaCoreForBricks\Support\AbilityI18n;

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

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

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

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

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

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

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

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

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

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

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

    private function callbackMethod(string $actionId): string
    {
        return match ($actionId) {
            'set_element_content' => 'executeSetElementContent',
            'add_section'         => 'executeAddSection',
            'add_container'       => 'executeAddContainer',
            'add_div'             => 'executeAddDiv',
            'add_heading'         => 'executeAddHeading',
            'add_text'            => 'executeAddText',
            'add_image'           => 'executeAddImage',
            'add_button'          => 'executeAddButton',
            default               => 'executeSetElementContent',
        };
    }

    /**
     * @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']];
        $placement = [
            'parent_id'    => ['type' => 'string'],
            'position'     => ['type' => 'string'],
            'reference_id' => ['type' => 'string'],
        ];
        $shortcut = [
            'content' => ['type' => 'object'],
            'classes' => ['type' => 'array', 'items' => ['type' => 'string']],
            'styles'  => ['type' => 'object'],
        ];

        if ($actionId === 'set_element_content') {
            return array_merge($dryRun, $page, [
                'element_id' => ['type' => 'string'],
                'content'    => ['type' => 'object'],
                'items'      => ['type' => 'array', 'items' => ['type' => 'object']],
            ]);
        }

        return array_merge($dryRun, $page, $placement, $shortcut);
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function outputSchema(): array
    {
        return [
            'success'          => ['type' => 'boolean'],
            'message'          => ['type' => 'string'],
            'post_id'          => ['type' => 'integer'],
            'area'             => ['type' => 'string'],
            'element_id'       => ['type' => 'string'],
            'element_ids'      => ['type' => 'array'],
            'name'             => ['type' => 'string'],
            'vocabulary_notes' => ['type' => 'array'],
            'impact'           => ['type' => 'object'],
        ];
    }
}
