/**
 * @file qdx_protocol.h
 * @brief Communication Protocol 2.0 Structures and Constants
 *
 * Platform-independent header for CH32 MCU and other systems.
 * All structures use 1-byte alignment. Focuses on safe uint8_t
 * serialization and avoiding hardware faults from unaligned access.
 */

#ifndef QDX_PROTOCOL_H
#define QDX_PROTOCOL_H

#include <stdint.h>

/* ============================================================
 * Protocol Constants
 * ============================================================ */
#define PROTO_MAGIC 0x55AA /* Frame Header Magic */
#define PROTO_VERSION 0x20 /* Protocol Version v2.0 */

/* Message Classes (Class) */
#define CLASS_CONTROL 0x01  /* Configuration / Control */
#define CLASS_DATA 0x02     /* Real-time Data Report */
#define CLASS_RESPONSE 0x03 /* ACK / NACK / Error */
#define CLASS_SYSTEM 0x04   /* Handshake / Heartbeat / Sync */

/* TLV Types */
#define TYPE_HANDSHAKE 0x01
#define TYPE_HEARTBEAT 0x02
#define TYPE_SYNC_TIME 0x03
#define TYPE_DEVID_ASSIGN 0x05
#define TYPE_TEMP_FRAME 0x10
#define TYPE_RAW_FRAME 0x11
#define TYPE_CONFIG_COMMON 0x20
#define TYPE_CONFIG_2D 0x22
#define TYPE_CONFIG_1D 0x23
#define TYPE_ACK_PAYLOAD 0x30
#define TYPE_DETECTION_RESULT 0x40

/* Flags */
#define FLAG_PRIORITY_MASK 0x03
#define FLAG_COMPRESSED 0x04
#define FLAG_ENCRYPTED 0x08
#define FLAG_ACK_REQ 0x10
#define FLAG_LAST_FRAGMENT 0x20

/* Frame Structure Sizes */
#define HEADER_SIZE 16    /* FrameHeader_t size */
#define TLV_HEADER_SIZE 3 /* TLV_t size (Type + Length) */
#define CRC_SIZE 2        /* CRC16 size */

/* Fragmentation limit */
#define MAX_FRAGMENT_PAYLOAD 1400

/* Error Codes */
#define ERR_NONE 0x0000
#define ERR_CRC 0x1001
#define ERR_VERSION 0x1002
#define ERR_LENGTH 0x1003
#define ERR_AUTH 0x2001
#define ERR_BUSY 0x2002
#define ERR_DEV_ID_CONFLICT 0x2003
#define ERR_PARAM 0x3001

/* ============================================================
 * Internal Protocol Structures (Packed to 1 byte)
 * ============================================================ */

#pragma pack(push, 1)

/**
 * @brief Frame Header (16 bytes)
 */
typedef struct {
  uint16_t Magic;
  uint8_t Version;
  uint16_t Length;
  uint16_t Sequence;
  uint32_t Timestamp;
  uint8_t Source;
  uint16_t DevID;
  uint8_t Class;
  uint8_t Flags;
} FrameHeader_t;

/**
 * @brief TLV Header (3 bytes)
 */
typedef struct {
  uint8_t Type;
  uint16_t Length;
} TLV_t;

/**
 * @brief Handshake (46 bytes)
 */
typedef struct {
  uint16_t ProtocolVersion;
  uint8_t DeviceUUID[16];
  uint8_t AuthToken[16];
  char HardwareVersion[8];
  char FirmwareVersion[8];
  uint32_t Capabilities;
} Handshake_t;

/**
 * @brief Heartbeat (6 bytes)
 */
typedef struct {
  uint32_t UpTime;
  uint8_t CpuLoad;
  uint8_t MemUsage;
} Heartbeat_t;

/**
 * @brief ACK Payload (5 bytes)
 */
typedef struct {
  uint16_t AckSeq;
  uint8_t Status;
  uint16_t ErrorCode;
} Ack_t;

/**
 * @brief Device ID Assignment (4 bytes)
 */
typedef struct {
  uint16_t NewDevID;
  uint16_t Reserved;
} DevIDAssignment_t;

/**
 * @brief Temperature Frame Header (18 bytes)
 */
typedef struct {
  uint32_t FrameNumber;
  uint16_t Width;
  uint16_t Height;
  int16_t MinTemp;
  int16_t MaxTemp;
  int16_t AvgTemp;
  int16_t RoiTemp;
  uint8_t FrameType;
  uint8_t Status;
  uint8_t Is2D;
  uint8_t Reserved;
} TemperatureFrameHeader_t;

/**
 * @brief 1D Temperature Point (4 bytes)
 */
typedef struct {
  uint16_t TimeOffset;
  uint16_t Temperature;
} TempPoint1D_t;

/**
 * @brief Detection Result (8 bytes)
 */
typedef struct {
  uint32_t FrameNumber;
  uint8_t Result;
  uint8_t Reserved[3];
} DetectionResult_t;

/**
 * @brief Common Configuration
 */
typedef struct {
  char PipelineId[16];
  uint8_t PipelineType;
  uint8_t WorkMode;
  uint8_t ConfigTag;
  uint8_t StrictnessLevel;
  uint8_t IsCustomMode;
  uint8_t Reserved[2];
} ConfigCommon_t;

/**
 * @brief 2D Configuration
 */
typedef struct {
  uint8_t Enabled;
  uint8_t IsLive;
  uint16_t DeviceId;
  uint16_t Width;
  uint16_t Height;
  uint8_t Fps;
  uint32_t Exposure;
  uint8_t AutoExposure;
  uint8_t MaskEnabled;
  int16_t MaskThreshold;
  uint16_t MaskWidth;
  uint16_t MaskHeight;
  int16_t Angle;
  uint16_t TargetWidth;
  uint16_t TargetHeight;
  uint8_t TriggerMode;
  uint8_t TriggerGpioLine;
  uint16_t TriggerDelayMs;
  uint8_t TriggerBurstCount;
  uint16_t TriggerInternalIntervalMs;
  int16_t TriggerTemperatureThreshold;
  uint16_t TriggerDebounceIntervalMs;
  uint8_t TriggerCondition;
  uint16_t TriggerRoiX;
  uint16_t TriggerRoiY;
  uint16_t TriggerRoiW;
  uint16_t TriggerRoiH;
  uint16_t NGioDelay;
  uint8_t OutputGpioLine;
  uint8_t AlarmGpioLine;
  uint16_t AlarmHoldMs;
  uint8_t StoreNgImagesOnly;
  uint8_t TrainingEnabled;
  uint16_t TrainingSampleThreshold;
  uint16_t ProcessingTimeoutMs;
  uint8_t MaxProcessingQueueSize;
  uint8_t Reserved;
} Config2D_t;

/**
 * @brief 1D Configuration
 */
typedef struct {
  uint8_t Enabled;
  uint8_t RunMode;
  uint8_t TriggerType;
  uint16_t BufferSize;
  int16_t TriggerTempLimit;
  uint16_t StartPointsToRemove;
  uint16_t ReferenceLength;
  uint16_t HighTimerLimit;
  uint16_t TimerCLimit;
  uint8_t NgCountLimit;
  uint16_t LSizeStart;
  uint16_t RSizeStart;
  uint16_t NGioDelay;
  uint8_t OutputGpioLine;
  uint8_t AlarmGpioLine;
  uint16_t AlarmHoldMs;
} Config1D_t;

#pragma pack(pop)

/* ============================================================
 * Application Level Business Structures
 * ============================================================ */

/**
 * @brief Raw Image Buffer provided by capture module
 */
typedef struct {
  uint16_t *pData;
  uint16_t Width;
  uint16_t Height;
  uint32_t FrameNumber;
} RawImageBuffer_t;

/**
 * @brief Preprocessing result metadata
 */
typedef struct {
  uint8_t *pValidData;
  uint32_t DataLength;
  uint16_t ValidWidth;
  uint16_t ValidHeight;
  int16_t MinTemp;
  int16_t MaxTemp;
  int16_t AvgTemp;
  int16_t RoiTemp;
  uint8_t Status;
  uint32_t FrameNumber;
} PreprocessResult_t;

/**
 * @brief Buffer wrapper for Zero-Copy TCP packet building
 */
typedef struct {
  uint8_t *pBuffer;
  uint32_t TotalCapacity;
  uint32_t HeadOffset; /* Reserved header space for envelope */
  uint32_t ValidPayloadLen;
} TcpTxBuffer_t;

/* System global config hook types */
typedef void (*ConfigUpdateCallback_t)(const ConfigCommon_t *common,
                                       const Config2D_t *cfg2d,
                                       const Config1D_t *cfg1d);
typedef void (*DetectionResultCallback_t)(uint32_t frameNumber,
                                          uint8_t resultStatus);

/* ============================================================
 * Protocol Utility Function Declarations
 * ============================================================ */

/* Calculate Modbus CRC16 */
uint16_t qdx_crc16_modbus(const uint8_t *data, int len);

/* Shift-safe write: 16-bit little-endian */
void qdx_write_u16_le(uint8_t *buf, uint16_t val);

/* Shift-safe write: 32-bit little-endian */
void qdx_write_u32_le(uint8_t *buf, uint32_t val);

/* Shift-safe read: 16-bit little-endian */
uint16_t qdx_read_u16_le(const uint8_t *buf);

/* Shift-safe read: 32-bit little-endian */
uint32_t qdx_read_u32_le(const uint8_t *buf);

/**
 * @brief Build a complete protocol frame using safe byte shifts.
 */
int qdx_build_frame(uint8_t *buf, uint8_t msg_class, uint8_t tlv_type,
                    const uint8_t *payload, uint16_t payload_len,
                    uint16_t dev_id, uint16_t seq, uint32_t timestamp,
                    uint8_t flags);

/**
 * @brief In-place frame build: 仅填写帧头并追加 CRC，不拷贝 payload。
 *        用于零拷贝场景，payload（含 TLV）已在 buf[HEADER_SIZE] 处就位。
 */
int qdx_build_frame_inplace(uint8_t *buf, uint8_t msg_class,
                            uint16_t payload_len, uint16_t dev_id, uint16_t seq,
                            uint32_t timestamp, uint8_t flags);

/**
 * @brief Build a fragmented payload frame (No TLV wrapper).
 */
int qdx_build_fragment_frame(uint8_t *buf, uint8_t msg_class,
                             const uint8_t *chunk, uint16_t chunk_len,
                             uint16_t dev_id, uint16_t seq, uint32_t timestamp,
                             uint8_t flags);

#endif /* QDX_PROTOCOL_H */
