/// @file uart_peripheral_esp.h
/// @brief Real ESP32 UART peripheral interface (thin header)
///
/// This header provides a thin interface to the ESP32 UART hardware.
/// All implementation details and ESP-IDF dependencies are in the .cpp file.
///
/// ## Design Philosophy
///
/// This implementation follows the "thin wrapper" pattern (mirroring PARLIO):
/// - NO business logic (pure delegation to ESP-IDF)
/// - NO state validation beyond what ESP-IDF provides
/// - NO performance overhead (inline-able calls)
/// - ALL logic stays in UartChannelEngine (testable via mock)
///
/// ## Thread Safety
///
/// Thread safety is inherited from ESP-IDF UART driver:
/// - initialize() NOT thread-safe (call once during setup)
/// - writeBytes() can be called from ISR context (ISR-safe)
/// - Other methods NOT thread-safe (caller synchronizes)
///
/// ## Error Handling
///
/// All methods return bool for success/failure:
/// - true: Operation succeeded (ESP_OK)
/// - false: Operation failed (any ESP-IDF error code)
///
/// Detailed error codes are NOT propagated through the interface.
/// The UartChannelEngine logs errors internally for debugging.

#pragma once

// IWYU pragma: private

#include "platforms/esp/is_esp.h"

#ifdef FL_IS_ESP32

#include "platforms/esp/32/drivers/uart/iuart_peripheral.h"
#include "fl/stl/noexcept.h"

namespace fl {

//=============================================================================
// Real Hardware Peripheral Interface
//=============================================================================

/// @brief Real ESP32 UART peripheral interface
///
/// Thin wrapper around ESP-IDF UART driver APIs. All methods delegate
/// directly to ESP-IDF with minimal overhead.
///
/// Unlike PARLIO, each UART instance is independent (no singleton pattern).
/// ESP32-C3 has 2 UARTs, ESP32-S3 has 3 UARTs - each can be instantiated
/// separately for multi-strip LED control.
class UartPeripheralEsp : public IUartPeripheral {
public:
    /// @brief Constructor
    UartPeripheralEsp() FL_NOEXCEPT;

    /// @brief Destructor - cleans up UART driver
    ~UartPeripheralEsp() override;

    // Prevent copying (UART handle cannot be shared)
    UartPeripheralEsp(const UartPeripheralEsp&) = delete;
    UartPeripheralEsp& operator=(const UartPeripheralEsp&) = delete;

    //=========================================================================
    // IUartPeripheral Interface Implementation
    //=========================================================================

    /// @brief Initialize UART peripheral with configuration
    /// @param config Hardware configuration (baud rate, pins, buffer sizes)
    /// @return true on success, false on error
    ///
    /// Maps to ESP-IDF: uart_param_config() + uart_driver_install() + uart_set_pin()
    bool initialize(const UartPeripheralConfig& config) FL_NOEXCEPT override;

    /// @brief Deinitialize UART peripheral and release resources
    ///
    /// Maps to ESP-IDF: uart_driver_delete()
    void deinitialize() FL_NOEXCEPT override;

    /// @brief Check if peripheral is initialized
    /// @return true if initialized, false otherwise
    bool isInitialized() const FL_NOEXCEPT override;

    /// @brief Write bytes to UART TX buffer
    /// @param data Pointer to data buffer
    /// @param length Number of bytes to transmit
    /// @return true on success, false on error
    ///
    /// Maps to ESP-IDF: uart_write_bytes()
    bool writeBytes(const u8* data, size_t length) FL_NOEXCEPT override;

    /// @brief Wait for all queued bytes to be transmitted
    /// @param timeout_ms Timeout in milliseconds (0 = non-blocking poll)
    /// @return true if transmission complete, false on timeout or error
    ///
    /// Maps to ESP-IDF: uart_wait_tx_done()
    bool waitTxDone(u32 timeout_ms) FL_NOEXCEPT override;

    /// @brief Check if UART is busy transmitting
    /// @return true if transmission in progress, false if idle
    bool isBusy() const FL_NOEXCEPT override;

    /// @brief Get current UART configuration
    /// @return Reference to current configuration
    const UartPeripheralConfig& getConfig() const FL_NOEXCEPT override;

private:
    UartPeripheralConfig mConfig;        ///< Stored configuration
    bool mInitialized;         ///< Initialization state
    u64 mResetExpireTime; ///< Timestamp when reset period ends (microseconds)
};

} // namespace fl

#endif // FL_IS_ESP32
