/**
 * OTA 二进制帧协议（BLE 0xFFE2 / UART）
 *
 * 帧格式：[HEAD0][HEAD1][VER][OP][SEQ_L][SEQ_H][LEN_L][LEN_H][PAYLOAD...][CRC8][TAIL]
 *  - HEAD: 0x4F 0x54 ('O','T')
 *  - VER:  0x02
 *  - CRC8: 从 VER 到 PAYLOAD 末字节逐字节 XOR
 *  - TAIL: 0x16
 *
 * OP_DATA 载荷 1～MAX 字节固件数据（UART 最大见 menuconfig）；设备回 OP_ACK：
 *  - 1 字节载荷：ACK [echo_byte][status]
 *  - 多块载荷：ACK [len_lo][len_hi][last_byte][status]
 * status=0 成功，非 0 须重传同一 SEQ 帧。
 */
#ifndef OTA_FRAME_PROTOCOL_H
#define OTA_FRAME_PROTOCOL_H

#include "sdkconfig.h"
#include <stdint.h>
#include <stdbool.h>

#define OTA_FRAME_MAGIC0        0x4F
#define OTA_FRAME_MAGIC1        0x54
#define OTA_FRAME_VERSION       0x02
#define OTA_FRAME_TAIL_BYTE     0x16

#define OTA_FRAME_OP_BEGIN      0x01
#define OTA_FRAME_OP_DATA       0x02
#define OTA_FRAME_OP_END        0x03
#define OTA_FRAME_OP_ACK        0x80
#define OTA_FRAME_OP_NAK        0x81

#define OTA_ACK_OK              0x00
#define OTA_ACK_ERR_FLASH       0x01
#define OTA_ACK_ERR_OVERFLOW    0x02
#define OTA_ACK_ERR_NO_SESSION  0x03
#define OTA_ACK_ERR_CRC         0x04
#define OTA_ACK_ERR_BAD_LEN     0x05
#define OTA_ACK_ERR_BAD_OP      0x06

#if CONFIG_APP_LINK_BLE
#define OTA_FRAME_MAX_PAYLOAD          240
#elif defined(CONFIG_APP_OTA_UART_MAX_CHUNK)
#define OTA_FRAME_MAX_PAYLOAD          CONFIG_APP_OTA_UART_MAX_CHUNK
#else
#define OTA_FRAME_MAX_PAYLOAD          1024
#endif
#define OTA_FRAME_DATA_CHUNK_RECOMMEND  128
#define OTA_FRAME_BUF_SIZE              (8 + OTA_FRAME_MAX_PAYLOAD + 2)

typedef void (*ota_frame_tx_fn)(const uint8_t *frame, uint16_t len, void *ctx);

void ota_frame_protocol_init(ota_frame_tx_fn tx, void *ctx);
void ota_frame_protocol_reset(void);

/** 喂入 RX 字节流（可含多帧）；内部组帧并应答 */
void ota_frame_rx_feed(const uint8_t *data, uint16_t len);

/** 帧解析器是否正在等待当前帧的后续字节 */
bool ota_frame_rx_is_active(void);

/** 是否像帧协议（'O'）或旧版裸 opcode */
bool ota_frame_rx_looks_framed(const uint8_t *data, uint16_t len);

int ota_frame_build(uint8_t op, uint16_t seq, const uint8_t *payload, uint16_t payload_len,
                    uint8_t *out, uint16_t out_cap, uint16_t *out_len);

#endif
