<?php
/**
 * Door 3 registration helpers for B13 page-behavior abilities.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks;

use LolaCoreForBricks\Handlers\PageBehaviorHandler;
use LolaCoreForBricks\Support\AbilityI18n;

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

        foreach (PageBehaviorAbilityMap::entries() as $actionId => $entry) {
            if ($entry['type'] === 'read') {
                $registrar->registerKnowledgeReadAbility(
                    $entry['slug'],
                    AbilityI18n::label($actionId),
                    AbilityI18n::description($actionId),
                    $this->inputSchema($actionId),
                    $this->outputSchema(),
                    [$this, $this->callbackMethod($actionId)]
                );
                continue;
            }

            $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 executeUpdatePageSettings(array $input): array
    {
        return $this->dispatch('updatePageSettings', $input, true);
    }

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

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

    /**
     * @param array<string, mixed> $input
     * @return array<string, mixed>
     */
    public function executeListDynamicDataTags(array $input): array
    {
        return (new PageBehaviorHandler())->listDynamicDataTags($input);
    }

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

    /**
     * @param array<string, mixed> $input
     * @return array<string, mixed>
     */
    private function dispatch(string $method, array $input, bool $write): array
    {
        unset($write);

        return (new PageBehaviorHandler())->{$method}($input, (bool) ($input['dry_run'] ?? false));
    }

    private function callbackMethod(string $actionId): string
    {
        return match ($actionId) {
            'update_page_settings'     => 'executeUpdatePageSettings',
            'set_element_conditions'   => 'executeSetElementConditions',
            'set_element_interactions' => 'executeSetElementInteractions',
            'list_dynamic_data_tags'   => 'executeListDynamicDataTags',
            'set_dynamic_content'      => 'executeSetDynamicContent',
            default                    => 'executeListDynamicDataTags',
        };
    }

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

        return match ($actionId) {
            'update_page_settings' => array_merge($dryRun, [
                'post_id'  => ['type' => 'integer'],
                'settings' => ['type' => 'object'],
            ]),
            'set_element_conditions' => array_merge($dryRun, $page, $element, [
                'conditions' => ['type' => 'array', 'items' => ['type' => 'object']],
            ]),
            'set_element_interactions' => array_merge($dryRun, $page, $element, [
                'interactions' => ['type' => 'array', 'items' => ['type' => 'object']],
            ]),
            'set_dynamic_content' => array_merge($dryRun, $page, $element, [
                'setting' => ['type' => 'string'],
                'tag'     => ['type' => 'string'],
            ]),
            default => [],
        };
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function outputSchema(): array
    {
        return [
            'success'     => ['type' => 'boolean'],
            'message'     => ['type' => 'string'],
            'post_id'     => ['type' => 'integer'],
            'element_id'  => ['type' => 'string'],
            'settings'    => ['type' => 'object'],
            'providers'   => ['type' => 'object'],
            'tags'        => ['type' => 'array'],
            'total'       => ['type' => 'integer'],
        ];
    }
}
