<?php

namespace AIPT\Api\Chatbot;

/**
 * Registry for managing chat actions.
 *
 * Provides extensible architecture for product card buttons.
 *
 * @package AIPT\Api\Chatbot
 * @since 2.5.0
 */
class ActionRegistry implements ActionRegistryInterface {

    /**
     * Registered actions.
     *
     * @var ChatActionInterface[]
     */
    private $actions = [];

    /**
     * Whether default actions have been registered.
     *
     * @var bool
     */
    private $defaults_registered = false;

    /**
     * Constructor.
     */
    public function __construct() {
        $this->registerDefaults();
    }

    /**
     * Register default actions.
     *
     * @return void
     */
    private function registerDefaults(): void {
        if ($this->defaults_registered) {
            return;
        }

        $this->register(new Actions\ViewProductAction());
        $this->register(new Actions\AddToCartAction());

        $this->defaults_registered = true;

        /**
         * Action hook for registering custom chatbot actions.
         *
         * @since 2.5.0
         * @param ActionRegistry $registry The action registry instance.
         */
        do_action('aipt_chatbot_register_actions', $this);
    }

    /**
     * Register a new action.
     *
     * @param ChatActionInterface $action Action instance.
     * @return void
     * @throws \InvalidArgumentException If action ID already registered.
     */
    public function register(ChatActionInterface $action): void {
        $id = $action->getId();

        if (isset($this->actions[$id])) {
            throw new \InvalidArgumentException(

                sprintf('Action with ID "%s" is already registered.', $id)
            );
        }

        $this->actions[$id] = $action;
    }

    /**
     * Unregister an action by ID.
     *
     * @param string $action_id Action identifier.
     * @return bool True if action was removed.
     */
    public function unregister(string $action_id): bool {
        if (!isset($this->actions[$action_id])) {
            return false;
        }

        unset($this->actions[$action_id]);
        return true;
    }

    /**
     * Get all registered actions.
     *
     * @return ChatActionInterface[] Array of actions sorted by priority.
     */
    public function getAll(): array {
        $actions = array_values($this->actions);

        usort($actions, function (ChatActionInterface $a, ChatActionInterface $b) {
            return $a->getPriority() <=> $b->getPriority();
        });

        return $actions;
    }

    /**
     * Get actions available for a specific product.
     *
     * @param int $product_id WooCommerce product ID.
     * @return ChatActionInterface[] Available actions.
     */
    public function getAvailableForProduct(int $product_id): array {
        $available = [];

        foreach ($this->getAll() as $action) {
            if ($action->isAvailable($product_id)) {
                $available[] = $action;
            }
        }

        return $available;
    }

    /**
     * Get a specific action by ID.
     *
     * @param string $action_id Action identifier.
     * @return ChatActionInterface|null Action instance or null.
     */
    public function get(string $action_id): ?ChatActionInterface {
        return $this->actions[$action_id] ?? null;
    }

    /**
     * Execute an action.
     *
     * @param string $action_id  Action identifier.
     * @param int    $product_id WooCommerce product ID.
     * @param array  $params     Additional parameters.
     * @return array Execution result.
     * @throws \InvalidArgumentException If action not found.
     */
    public function execute(string $action_id, int $product_id, array $params = []): array {
        $action = $this->get($action_id);

        if (!$action) {
            throw new \InvalidArgumentException(

                sprintf('Action with ID "%s" not found.', $action_id)
            );
        }

        if (!$action->isAvailable($product_id)) {
            return [
                'success' => false,
                'message' => __('This action is not available for this product.', 'ai-product-tools'),
            ];
        }

        return $action->execute($product_id, $params);
    }

    /**
     * Get action buttons data for a product.
     *
     * @param int    $product_id WooCommerce product ID.
     * @param string $language   Language code for labels.
     * @param array  $settings   Chatbot behavior settings.
     * @return array Array of action button data.
     */
    public function getActionButtonsForProduct(int $product_id, string $language = 'en', array $settings = []): array {
        $show_view_product = $settings['show_view_product'] ?? true;
        $show_add_to_cart = $settings['show_add_to_cart'] ?? true;

        $buttons = [];

        foreach ($this->getAll() as $action) {
            $action_id = $action->getId();

            if ($action_id === 'view_product' && !$show_view_product) {
                continue;
            }
            if ($action_id === 'add_to_cart' && !$show_add_to_cart) {
                continue;
            }

            $is_available = $action->isAvailable($product_id);

            $buttons[] = [
                'type' => $action_id,
                'label' => $action->getLabel($language),
                'icon' => $action->getIcon(),
                'enabled' => $is_available,
            ];
        }

        return $buttons;
    }
}
