#ifndef INTEGRATION_LAYER_H
#define INTEGRATION_LAYER_H

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

#include "uart_driver.h"
#include "midea_protocol.h"
#include "zigbee_zcl.h"

/**
 * @brief Integration layer configuration
 */
typedef struct {
    uart_driver_t *uart_driver;
    uint32_t command_queue_size;
    uint32_t command_timeout_ms;
} integration_layer_config_t;

/**
 * @brief Integration layer handle
 */
typedef struct {
    uart_driver_t *uart_driver;
    midea_control_t last_command;
    bool last_command_valid;
    uint32_t last_command_time;
    uint32_t command_spacing_ms;
    bool initialized;
} integration_layer_t;

/**
 * @brief Initialize integration layer
 *
 * @param layer Pointer to integration layer structure
 * @param config Integration layer configuration
 * @return true if successful, false otherwise
 */
bool integration_layer_init(integration_layer_t *layer, const integration_layer_config_t *config);

/**
 * @brief Deinitialize integration layer
 *
 * @param layer Pointer to integration layer structure
 */
void integration_layer_deinit(integration_layer_t *layer);

/**
 * @brief Handle incoming Zigbee command and convert to UART command
 *
 * @param layer Pointer to integration layer structure
 * @param endpoint Zigbee endpoint ID
 * @param cluster_id Zigbee cluster ID
 * @param command_id Zigbee command ID
 * @param payload Command payload
 * @param payload_length Length of payload
 * @param uart_buffer Buffer to store generated UART command (optional, can be NULL)
 * @param uart_length Pointer to store length of generated UART command (optional, can be NULL)
 * @return true if command processed successfully
 */
bool integration_layer_handle_zigbee_command(integration_layer_t *layer,
                                            uint8_t endpoint, uint16_t cluster_id,
                                            uint8_t command_id, const uint8_t* payload,
                                            uint16_t payload_length, uint8_t* uart_buffer,
                                            size_t* uart_length);

/**
 * @brief Send MideaUART command with rate limiting
 *
 * @param layer Pointer to integration layer structure
 * @param control MideaUART control structure to send
 * @return true if command sent successfully
 */
bool integration_layer_send_midea_command(integration_layer_t *layer,
                                         const midea_control_t *control);

/**
 * @brief Poll for AC status via UART and update Zigbee attributes
 *
 * @param layer Pointer to integration layer structure
 * @return true if status polling successful
 */
bool integration_layer_poll_and_update_status(integration_layer_t *layer);

/**
 * @brief Map ZCL system_mode to MideaUART mode
 *
 * @param zcl_mode ZCL system mode (0=Off, 1=Auto, 3=Cool, 4=Heat)
 * @return Corresponding MideaUART mode
 */
midea_mode_t integration_layer_map_zcl_to_midea_mode(uint8_t zcl_mode);

/**
 * @brief Map MideaUART mode to ZCL system_mode
 *
 * @param midea_mode MideaUART mode
 * @return Corresponding ZCL system mode (0=Off, 1=Auto, 3=Cool, 4=Heat)
 */
uint8_t integration_layer_map_midea_to_zcl_mode(midea_mode_t midea_mode);

/**
 * @brief Convert ZCL temperature (0.01°C) to MideaUART format
 *
 * @param zcl_temp Temperature in ZCL format (0.01°C units)
 * @return Temperature in MideaUART format (still 0.01°C units, just passed through)
 */
int16_t integration_layer_convert_zcl_temperature(int16_t zcl_temp);

/**
 * @brief Convert MideaUART temperature to ZCL format
 *
 * @param midea_temp Temperature in MideaUART format (0.01°C units)
 * @return Temperature in ZCL format (0.01°C units)
 */
int16_t integration_layer_convert_midea_temperature(int16_t midea_temp);

/**
 * @brief Convert Zigbee ZCL attributes to MideaUART control structure
 *
 * @param zcl_attrs Pointer to ZCL thermostat attributes
 * @param uart_cmd Pointer to store converted MideaUART control structure
 * @return true if conversion successful, false otherwise
 */
bool integration_layer_zigbee_to_uart(const zcl_thermostat_attrs_t *zcl_attrs,
                                     midea_control_t *uart_cmd);

/**
 * @brief Convert MideaUART control structure to Zigbee ZCL attributes
 *
 * @param uart_cmd Pointer to MideaUART control structure
 * @param zcl_attrs Pointer to store converted ZCL thermostat attributes
 * @return true if conversion successful, false otherwise
 */
bool integration_layer_uart_to_zigbee(const midea_control_t *uart_cmd,
                                     zcl_thermostat_attrs_t *zcl_attrs);

/**
 * @brief Handle incoming UART response and update Zigbee attributes
 * @param layer Pointer to integration layer structure
 * @param uart_response Incoming UART response
 * @param uart_length Length of UART response
 * @param zcl_attrs Pointer to store updated Zigbee attributes
 * @return true if handling successful, false otherwise
 */
bool integration_layer_handle_uart_response(integration_layer_t *layer,
                                           const uint8_t* uart_response,
                                           size_t uart_length,
                                           zcl_thermostat_attrs_t* zcl_attrs);

/**
 * @brief Handle schedule command from Zigbee
 *
 * @param endpoint Zigbee endpoint ID
 * @param payload Schedule command payload
 * @param payload_length Length of payload
 * @return true if command handled successfully
 */
bool integration_layer_handle_schedule_command(uint8_t endpoint, const uint8_t* payload,
                                              uint16_t payload_length);

#endif // INTEGRATION_LAYER_H