package de.assecutor.votianlt.messaging.plugin;

import java.util.concurrent.CompletableFuture;

/**
 * Interface for messaging transport plugins.
 * Plugins implement specific transport protocols (MQTT, WebSocket, gRPC, etc.)
 * and provide a unified interface for the messaging layer.
 *
 * The plugin is responsible for managing the internal topic/channel structure.
 * The messaging layer only uses clientId and messageType as identifiers.
 */
public interface MessagingPlugin {

    /**
     * Initialize the plugin with configuration.
     * Called once during application startup.
     *
     * @param config Plugin-specific configuration
     * @throws PluginException if initialization fails
     */
    void init(PluginConfig config) throws PluginException;

    /**
     * Shutdown the plugin and release resources.
     * Called during application shutdown.
     *
     * @throws PluginException if shutdown fails
     */
    void exit() throws PluginException;

    /**
     * Callback when connection state changes.
     * The plugin should call this method when the underlying transport
     * connection state changes (connected, disconnected, error).
     *
     * @param listener Connection state listener
     */
    void setConnectionListener(ConnectionStateListener listener);

    /**
     * Send a message to a specific client.
     * The plugin is responsible for determining the correct topic/channel based on the messageType.
     *
     * @param clientId    Target client identifier
     * @param messageType Type of message (e.g., "jobs", "message", "auth", "task")
     * @param payload     Message payload as byte array
     * @param options     Transport-specific options
     * @return CompletableFuture that completes when message is sent
     * @throws PluginException if sending fails
     */
    CompletableFuture<Void> sendToClient(String clientId, String messageType, byte[] payload, SendOptions options) throws PluginException;

    /**
     * Send an acknowledgment to a specific client.
     * The plugin is responsible for determining the correct ACK topic/channel.
     *
     * @param clientId  Target client identifier
     * @param messageId Message ID being acknowledged
     * @param payload   ACK payload as byte array
     * @param options   Transport-specific options
     * @return CompletableFuture that completes when ACK is sent
     * @throws PluginException if sending fails
     */
    CompletableFuture<Void> sendAckToClient(String clientId, String messageId, byte[] payload, SendOptions options) throws PluginException;

    /**
     * Register a handler for incoming messages of a specific type from clients.
     * The plugin is responsible for subscribing to the appropriate topics/channels.
     *
     * @param messageType Type of message to handle (e.g., "task_completed", "message", "jobs/assigned", "login")
     * @param handler     Message handler to be called when a message is received
     * @throws PluginException if registration fails
     */
    void registerMessageHandler(String messageType, ClientMessageHandler handler) throws PluginException;

    /**
     * Register a handler for incoming acknowledgments from clients.
     * The plugin is responsible for subscribing to the appropriate ACK topics/channels.
     *
     * @param handler ACK handler to be called when an ACK is received
     * @throws PluginException if registration fails
     */
    void registerAckHandler(AckHandler handler) throws PluginException;

    /**
     * Check if the plugin is currently connected.
     *
     * @return true if connected, false otherwise
     */
    boolean isConnected();

    /**
     * Get the plugin name/type identifier.
     *
     * @return Plugin name (e.g., "mqtt", "websocket", "grpc")
     */
    String getPluginName();

    /**
     * Get plugin version.
     *
     * @return Plugin version string
     */
    String getPluginVersion();

    /**
     * Get plugin metadata/information.
     *
     * @return Plugin metadata
     */
    PluginMetadata getMetadata();

    /**
     * Callback interface for connection state changes.
     */
    @FunctionalInterface
    interface ConnectionStateListener {
        /**
         * Called when connection state changes.
         *
         * @param event Connection state event
         */
        void onConnectionStateChanged(ConnectionStateEvent event);
    }

    /**
     * Handler for received messages from clients.
     * Includes the clientId extracted from the topic/channel.
     */
    @FunctionalInterface
    interface ClientMessageHandler {
        /**
         * Called when a message is received from a client.
         *
         * @param clientId Client identifier extracted from the topic/channel
         * @param payload  Message payload as byte array
         */
        void onMessageReceived(String clientId, byte[] payload);
    }

    /**
     * Handler for received acknowledgments from clients.
     */
    @FunctionalInterface
    interface AckHandler {
        /**
         * Called when an ACK is received from a client.
         *
         * @param messageId Message ID being acknowledged
         * @param payload   ACK payload as byte array
         */
        void onAckReceived(String messageId, byte[] payload);
    }
}

