<?php

/**
 * Command Dispatcher
 *
 * @package _121Digital\Connect
 */

namespace _121Digital\Connect\Commands;

use _121Digital\Connect\Commands\Favicon\Get as FaviconGet;
use _121Digital\Connect\Commands\Matomo\HasTracker;
use _121Digital\Connect\Commands\Matomo\SetTrackingCode;
use _121Digital\Connect\Commands\Plugin\Update as PluginUpdate;
use _121Digital\Connect\Commands\Users\CreateSession;
use _121Digital\Connect\Commands\Users\Get as UsersGet;
use _121Digital\Connect\Commands\WP\GetMeta;

/**
 * Command Dispatcher Class
 *
 * Maps and dispatches commands to their respective handlers
 */
class CommandDispatcher
{
    /**
     * Command map
     *
     * @var array
     */
    private array $commandMap = [];

    /**
     * Constructor - Initialize command map
     */
    public function __construct()
    {
        $this->initializeCommandMap();
    }

    /**
     * Initialize the command map
     *
     * @return void
     */
    private function initializeCommandMap(): void
    {
        $this->commandMap = [
            'wp getmeta' => new GetMeta(),
            'users get' => new UsersGet(),
            'users createsession' => new CreateSession(),
            'favicon get' => new FaviconGet(),
            'plugin update' => new PluginUpdate(),
            'matomo hastracker' => new HasTracker(),
            'matomo settrackingcode' => new SetTrackingCode(),
        ];
    }

    /**
     * Dispatch a command
     *
     * @param string $command Command name
     * @param array $arguments Command arguments
     * @return array Result array
     * @throws \Exception If command doesn't exist
     */
    public function dispatch(string $command, array $arguments = []): array
    {
        if (!isset($this->commandMap[$command])) {
            throw new \Exception(
                'Invalid request. Command "' . $command . '" does not exist. The plugin might be outdated.'
            );
        }

        $commandInstance = $this->commandMap[$command];
        $commandInstance->setArgs($arguments);

        try {
            $result = $commandInstance->execute();

            return [
                'success' => $result['success'],
                'message' => $result['message'],
                'data' => $result['data'] ?? [],
            ];
        } catch (\Exception $e) {
            throw new \Exception('Error during execute command thread: ' . $e->getMessage());
        }
    }

    /**
     * Register this component (required for Plugin initialization)
     *
     * @return void
     */
    public function register(): void
    {
        // No hooks to register for command dispatcher
    }

    /**
     * Get all available commands
     *
     * @return array
     */
    public function getAvailableCommands(): array
    {
        return array_keys($this->commandMap);
    }

    /**
     * Check if a command exists
     *
     * @param string $command
     * @return bool
     */
    public function hasCommand(string $command): bool
    {
        return isset($this->commandMap[$command]);
    }
}
