<?php
/**
 * Door 3 registration helpers for B5 design-system write abilities.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks;

use LolaCoreForBricks\Handlers\DesignSystemHandler;
use LolaCoreForBricks\Support\AbilityI18n;

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

        foreach (DesignSystemAbilityMap::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 executeSetGlobalVariable(array $input): array
    {
        return $this->dispatch('setGlobalVariable', $input);
    }

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

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

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

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

        return (new DesignSystemHandler())->{$method}($input, $dryRun);
    }

    private function callbackMethod(string $actionId): string
    {
        return match ($actionId) {
            'set_global_variable'   => 'executeSetGlobalVariable',
            'delete_global_variable' => 'executeDeleteGlobalVariable',
            'update_color_palette'  => 'executeUpdateColorPalette',
            'update_theme_style'    => 'executeUpdateThemeStyle',
            default                 => 'executeSetGlobalVariable',
        };
    }

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

        return match ($actionId) {
            'set_global_variable' => array_merge($dryRun, [
                'name'      => ['type' => 'string'],
                'value'     => ['type' => 'string'],
                'type'      => ['type' => 'string'],
                'category'  => ['type' => 'string'],
                'variables' => ['type' => 'array'],
            ]),
            'delete_global_variable' => array_merge($dryRun, [
                'variable' => ['type' => 'string'],
            ]),
            'update_color_palette' => array_merge($dryRun, [
                'id'       => ['type' => 'string'],
                'name'     => ['type' => 'string'],
                'colors'   => ['type' => 'array'],
                'palette'  => ['type' => 'object'],
                'palettes' => ['type' => 'array'],
            ]),
            'update_theme_style' => array_merge($dryRun, [
                'style'      => ['type' => 'string'],
                'label'      => ['type' => 'string'],
                'settings'   => ['type' => 'object'],
                'conditions' => ['type' => 'array'],
            ]),
            default => $dryRun,
        };
    }

    /**
     * @return array<string, array<string, string>>
     */
    private function outputSchema(string $actionId): array
    {
        $base = [
            'success'  => ['type' => 'boolean'],
            'message'  => ['type' => 'string'],
            'coverage' => ['type' => 'object'],
        ];

        return match ($actionId) {
            'set_global_variable' => array_merge($base, [
                'batch'            => ['type' => 'object'],
                'vocabulary_notes' => ['type' => 'array'],
            ]),
            'delete_global_variable' => array_merge($base, [
                'impact' => ['type' => 'object'],
            ]),
            'update_color_palette', 'update_theme_style' => $base,
            default => $base,
        };
    }
}
