<?php
/**
 * Door 3 registration helpers for B14 WooCommerce surface abilities.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks;

use LolaCoreForBricks\Handlers\WooSurfaceHandler;
use LolaCoreForBricks\Support\AbilityI18n;

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

        foreach (WooSurfaceAbilityMap::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 executeGetWooBricksSurface(array $input): array
    {
        return (new WooSurfaceHandler())->getWooBricksSurface($input);
    }

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

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

    /**
     * @param array<string, mixed> $input
     * @return array<string, mixed>
     */
    public function executeGetProductElementsCatalog(array $input): array
    {
        return (new WooSurfaceHandler())->getProductElementsCatalog($input);
    }

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

    private function callbackMethod(string $actionId): string
    {
        return match ($actionId) {
            'get_woo_bricks_surface'       => 'executeGetWooBricksSurface',
            'create_woo_template'          => 'executeCreateWooTemplate',
            'add_product_element'          => 'executeAddProductElement',
            'get_product_elements_catalog' => 'executeGetProductElementsCatalog',
            default                        => 'executeGetWooBricksSurface',
        };
    }

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

        return match ($actionId) {
            'create_woo_template' => array_merge($dryRun, [
                'kind'       => ['type' => 'string'],
                'type'       => ['type' => 'string'],
                'title'      => ['type' => 'string'],
                'status'     => ['type' => 'string'],
                'conditions' => ['type' => 'array', 'items' => ['type' => 'object']],
            ]),
            'add_product_element' => array_merge($dryRun, [
                'post_id'      => ['type' => 'integer'],
                'area'         => ['type' => 'string'],
                'parent_id'    => ['type' => 'string'],
                'position'     => ['type' => 'string'],
                'reference_id' => ['type' => 'string'],
                'name'         => ['type' => 'string'],
                'element'      => ['type' => 'string'],
                'settings'     => ['type' => 'object'],
            ]),
            default => [],
        };
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function outputSchema(): array
    {
        return [
            'success'             => ['type' => 'boolean'],
            'message'             => ['type' => 'string'],
            'templates'           => ['type' => 'object'],
            'extra_woo_templates' => ['type' => 'array'],
            'elements_used'       => ['type' => 'array'],
            'groups'              => ['type' => 'array'],
            'total'               => ['type' => 'integer'],
            'kind'                => ['type' => 'string'],
            'template_id'         => ['type' => 'integer'],
            'element_id'          => ['type' => 'string'],
            'impact'              => ['type' => 'object'],
            'preview'             => ['type' => 'object'],
        ];
    }
}
