<?php
/**
 * Door 3 registration helpers for B15 batch composition abilities.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks;

use LolaCoreForBricks\Handlers\BatchCompositionHandler;
use LolaCoreForBricks\Support\AbilityI18n;

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

        foreach (BatchCompositionAbilityMap::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 executeCloneStructure(array $input): array
    {
        return $this->dispatch('cloneStructure', $input);
    }

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

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

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

    private function callbackMethod(string $actionId): string
    {
        return match ($actionId) {
            'clone_structure'     => 'executeCloneStructure',
            'bulk_update_content' => 'executeBulkUpdateContent',
            'bulk_apply_classes'  => 'executeBulkApplyClasses',
            default               => 'executeCloneStructure',
        };
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function inputSchema(string $actionId): array
    {
        $batch = [
            'dry_run'    => ['type' => 'boolean'],
            'batch_size' => ['type' => 'integer'],
            'offset'     => ['type' => 'integer'],
        ];
        $targets  = ['targets' => ['type' => 'array', 'items' => ['type' => 'object']]];
        $selector = ['selector' => ['type' => 'object']];

        return match ($actionId) {
            'clone_structure' => array_merge($batch, $targets, [
                'source'       => ['type' => 'object'],
                'element_id'   => ['type' => 'string'],
                'area'         => ['type' => 'string'],
                'position'     => ['type' => 'string'],
                'parent_id'    => ['type' => 'string'],
                'reference_id' => ['type' => 'string'],
            ]),
            'bulk_update_content' => array_merge($batch, $targets, $selector, [
                'content' => ['type' => 'object'],
            ]),
            default => array_merge($batch, $targets, $selector, [
                'add'     => ['type' => 'array', 'items' => ['type' => 'string']],
                'remove'  => ['type' => 'array', 'items' => ['type' => 'string']],
                'classes' => ['type' => 'array', 'items' => ['type' => 'string']],
            ]),
        };
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function outputSchema(): array
    {
        return [
            'success'       => ['type' => 'boolean'],
            'message'       => ['type' => 'string'],
            'impact'        => ['type' => 'object'],
            'done'          => ['type' => 'integer'],
            'total'         => ['type' => 'integer'],
            'finished'      => ['type' => 'boolean'],
            'offset'        => ['type' => 'integer'],
            'elapsed_ms'    => ['type' => 'integer'],
            'written'       => ['type' => 'array'],
            'stopped_at'    => ['type' => 'object'],
            'remaining'     => ['type' => 'array'],
            'coverage'      => ['type' => 'object'],
            'coverage_note' => ['type' => 'string'],
        ];
    }
}
