<?php
/**
 * Door 3 registration helpers for B4 global class write abilities.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks;

use LolaCoreForBricks\Handlers\ClassHandler;
use LolaCoreForBricks\Support\AbilityI18n;

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

        foreach (ClassWriteAbilityMap::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 executeCreateGlobalClass(array $input): array
    {
        return $this->dispatch('createGlobalClass', $input);
    }

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

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

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

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

    /**
     * @param array<string, mixed> $input
     * @return array<string, mixed>
     */
    public function executeRestoreGlobalClass(array $input): array
    {
        return $this->dispatch('restoreGlobalClass', $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 ClassHandler())->{$method}($input, $dryRun);
    }

    private function callbackMethod(string $actionId): string
    {
        return match ($actionId) {
            'create_global_class'          => 'executeCreateGlobalClass',
            'update_global_class_settings' => 'executeUpdateGlobalClassSettings',
            'rename_global_class'          => 'executeRenameGlobalClass',
            'merge_global_classes'         => 'executeMergeGlobalClasses',
            'trash_global_classes'         => 'executeTrashGlobalClasses',
            'restore_global_class'         => 'executeRestoreGlobalClass',
            default                        => 'executeCreateGlobalClass',
        };
    }

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

        return match ($actionId) {
            'create_global_class' => array_merge($dryRun, [
                'name'     => ['type' => 'string'],
                'category' => ['type' => 'string'],
                'settings' => ['type' => 'object'],
            ]),
            'update_global_class_settings' => array_merge($dryRun, [
                'class'    => ['type' => 'string'],
                'settings' => ['type' => 'object'],
            ]),
            'rename_global_class' => array_merge($dryRun, [
                'class'    => ['type' => 'string'],
                'new_name' => ['type' => 'string'],
            ]),
            'merge_global_classes' => array_merge($dryRun, [
                'source_class' => ['type' => 'string'],
                'target_class' => ['type' => 'string'],
            ]),
            'trash_global_classes' => array_merge($dryRun, [
                'classes' => ['type' => 'array', 'items' => ['type' => 'string']],
            ]),
            'restore_global_class' => array_merge($dryRun, [
                'class' => ['type' => 'string'],
            ]),
            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) {
            'create_global_class' => array_merge($base, [
                'vocabulary_notes' => ['type' => 'array'],
            ]),
            'update_global_class_settings', 'restore_global_class' => $base,
            'rename_global_class', 'merge_global_classes', 'trash_global_classes' => array_merge($base, [
                'impact' => ['type' => 'object'],
            ]),
            default => $base,
        };
    }
}
