<?php
/**
 * Door 3 registration helpers for B11 template write abilities.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks;

use LolaCoreForBricks\Handlers\TemplateWriteHandler;
use LolaCoreForBricks\Support\AbilityI18n;

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

        foreach (TemplateWriteAbilityMap::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 executeCreateTemplate(array $input): array
    {
        return $this->dispatch('createTemplate', $input);
    }

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

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

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

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

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

    private function callbackMethod(string $actionId): string
    {
        return match ($actionId) {
            'create_template'            => 'executeCreateTemplate',
            'set_template_content'       => 'executeSetTemplateContent',
            'update_template_conditions' => 'executeUpdateTemplateConditions',
            'duplicate_template'         => 'executeDuplicateTemplate',
            'delete_template'            => 'executeDeleteTemplate',
            default                      => 'executeCreateTemplate',
        };
    }

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

        return match ($actionId) {
            'create_template' => array_merge($dryRun, [
                'title'       => ['type' => 'string'],
                'type'        => ['type' => 'string'],
                'status'      => ['type' => 'string'],
                'entire_site' => ['type' => 'boolean'],
                'conditions'  => ['type' => 'array', 'items' => ['type' => 'object']],
            ]),
            'set_template_content' => array_merge($dryRun, $templateId, [
                'area'     => ['type' => 'string'],
                'elements' => ['type' => 'array', 'items' => ['type' => 'object']],
            ]),
            'update_template_conditions' => array_merge($dryRun, $templateId, [
                'entire_site' => ['type' => 'boolean'],
                'conditions'  => ['type' => 'array', 'items' => ['type' => 'object']],
            ]),
            default => array_merge($dryRun, $templateId),
        };
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function outputSchema(): array
    {
        return [
            'success'     => ['type' => 'boolean'],
            'message'     => ['type' => 'string'],
            'template_id' => ['type' => 'integer'],
            'title'       => ['type' => 'string'],
            'type'        => ['type' => 'string'],
            'conditions'  => ['type' => 'array'],
            'preview'     => ['type' => 'object'],
            'impact'      => ['type' => 'object'],
            'resolution'  => ['type' => 'object'],
        ];
    }
}
