<?php
declare(strict_types=1);

namespace Ekesto\CacheInvalidator\Integrations\Forms\Adapters;

use Ekesto\CacheInvalidator\Integrations\Forms\FormAdapterInterface;

/**
 * WPForms adapter.
 */
final class WPFormsAdapter implements FormAdapterInterface
{
    use NormalizesFormIds;

    /**
     * Return adapter key.
     *
     * @return string
     */
    public function key(): string
    {
        return 'wpforms';
    }

    /**
     * Return adapter label.
     *
     * @return string
     */
    public function label(): string
    {
        return 'WPForms';
    }

    /**
     * Return whether WPForms is available.
     *
     * @return bool
     */
    public function isAvailable(): bool
    {
        return defined('WPFORMS_VERSION') || post_type_exists('wpforms');
    }

    /**
     * Register form change hooks.
     *
     * @param callable $onFormChanged Change callback.
     * @return void
     */
    public function registerHooks(callable $onFormChanged): void
    {
        add_action('save_post_wpforms', static function (int $postId, \WP_Post $post, bool $update) use ($onFormChanged): void {
            if (wp_is_post_autosave($postId) || wp_is_post_revision($postId)) {
                return;
            }

            $onFormChanged('wpforms', (string) $postId, [
                'event' => $update ? 'update' : 'create',
                'source_hook' => 'save_post_wpforms',
                'post_status' => (string) $post->post_status,
            ]);
        }, 20, 3);

        add_action('deleted_post', static function (int $postId, \WP_Post $post) use ($onFormChanged): void {
            if ($post->post_type !== 'wpforms') {
                return;
            }

            $onFormChanged('wpforms', (string) $postId, [
                'event' => 'delete',
                'source_hook' => 'deleted_post',
            ]);
        }, 20, 2);

        add_action('trashed_post', static function (int $postId) use ($onFormChanged): void {
            $post = get_post($postId);
            if (!$post instanceof \WP_Post || $post->post_type !== 'wpforms') {
                return;
            }

            $onFormChanged('wpforms', (string) $postId, [
                'event' => 'delete',
                'source_hook' => 'trashed_post',
            ]);
        }, 20, 1);
    }

    /**
     * Return shortcode tags.
     *
     * @return string[]
     */
    public function shortcodes(): array
    {
        return ['wpforms'];
    }

    /**
     * Return block names.
     *
     * @return string[]
     */
    public function blockNames(): array
    {
        return ['wpforms/form-selector'];
    }

    /**
     * Return candidate needles.
     *
     * @return string[]
     */
    public function candidateNeedles(): array
    {
        return ['wpforms', 'form-selector'];
    }

    /**
     * Extract form IDs from text.
     *
     * @param string $text Source text.
     * @return string[]
     */
    public function extractFormIdsFromContent(string $text): array
    {
        if ($text === '') {
            return [];
        }

        $matches = [];

        if (preg_match_all('/\\[wpforms[^\]]*\\bid\\s*=\\s*["\']?([^"\'\]\s]+)["\']?/i', $text, $shortcodeMatches) > 0) {
            $matches = array_merge($matches, $shortcodeMatches[1] ?? []);
        }

        if (preg_match_all('/wp:wpforms\\/form-selector\\s+\{[^\}]*"formId"\\s*:\\s*"?([A-Za-z0-9_-]+)"?/i', $text, $blockMatches) > 0) {
            $matches = array_merge($matches, $blockMatches[1] ?? []);
        }

        return $this->normalizeIds($matches);
    }

}
