#pragma once

#include <memory>
#include <span>
#include <string_view>

// Forward declaration to avoid circular dependency
struct Connection;

/**
 * Abstract interface for handling connection data processing.
 *
 * This interface decouples protocol-specific logic (HTTP, WebSocket, etc.)
 * from the underlying networking infrastructure. Implementations handle
 * parsing incoming data and generating appropriate responses.
 *
 * The networking layer manages connection lifecycle, I/O multiplexing,
 * and efficient data transfer, while handlers focus purely on protocol logic.
 */
struct ConnectionHandler {
public:
  virtual ~ConnectionHandler() = default;

  /**
   * Process incoming data from a connection.
   *
   * @param data Incoming data buffer (may be partial message)
   * @param conn_ptr Unique pointer to connection - handler can take ownership
   * by releasing it
   *
   * Implementation should:
   * - Parse incoming data using arena allocator when needed
   * - Use conn_ptr->append_message() to queue response data to be sent
   * - Handle partial messages and streaming protocols appropriately
   * - Can take ownership by calling conn_ptr.release() to pass to other threads
   * - If ownership is taken, handler must call Server::release_back_to_server()
   * when done
   * @note `data` is *not* owned by the connection arena, and its lifetime ends
   * after the call to on_data_arrived.
   * @note May be called from an arbitrary server thread.
   */
  virtual void on_data_arrived(std::string_view /*data*/,
                               std::unique_ptr<Connection> &) {};

  /**
   * Called when data has been successfully written to the connection.
   *
   * This is called during write operations to indicate progress, useful for:
   * - Streaming large responses (files, data feeds, etc.)
   * - Implementing backpressure for continuous data streams
   * - Progress monitoring for long-running transfers
   *
   * @param conn_ptr Connection that made write progress - handler can take
   * ownership
   * @note May be called from an arbitrary server thread.
   * @note Called during writes, not necessarily when buffer becomes empty
   */
  virtual void on_write_progress(std::unique_ptr<Connection> &) {}

  /**
   * Called when the connection's outgoing write buffer becomes empty.
   *
   * This indicates all queued messages have been successfully written
   * to the socket. Useful for:
   * - Resetting arena allocators safely
   * - Implementing keep-alive connection reuse
   * - Closing connections after final response
   * - Relieving backpressure conditions
   *
   * @param conn_ptr Connection with empty write buffer - handler can take
   * ownership
   * @note May be called from an arbitrary server thread.
   * @note Only called on transitions from non-empty → empty buffer
   */
  virtual void on_write_buffer_drained(std::unique_ptr<Connection> &) {}

  /**
   * Called when a new connection is established.
   *
   * @param conn Newly established connection
   *
   * Use this for:
   * - Connection-specific initialization.
   * @note May be called from an arbitrary server thread.
   */
  virtual void on_connection_established(Connection &) {}

  /**
   * Called when a connection is about to be closed.
   *
   * @param conn Connection being closed
   *
   * Use this for:
   * - Cleanup of connection-specific resources.
   * @note May be called from an arbitrary server thread.
   */
  virtual void on_connection_closed(Connection &) {}

  /**
   * @brief Called after a batch of connections has been processed.
   *
   * This hook is called after on_data_arrived, on_write_progress, or
   * on_write_buffer_drained has been called for each connection in the batch.
   * The handler can take ownership of the connections by moving the unique_ptr
   * out of the span. Any connections left in the span will remain owned by the
   * server.
   *
   * @param batch A span of unique_ptrs to the connections in the batch.
   */
  virtual void
  on_batch_complete(std::span<std::unique_ptr<Connection>> /*batch*/) {}
};
