/*
 * @Author: mypx
 * @Date: 2025-08-01 16:41:44
 * @LastEditTime: 2025-09-26 09:21:13
 * @LastEditors: mypx mypx_coder@163.com
 * @Description: 
 */
#include "mb_command.h"
#include "et_log.h"
#include "etk_byte_conv.h"
#include "tec_control.h"
#include <stdio.h>
#include <string.h>

static mb_cmd_handler_t *cmd_handler = NULL;
static mb_command_t     *mb_cmd      = NULL;

// external declaration for temperature control
extern tec_control_t *tec_control;
// Note: g_mb_regs was removed; use mb_command_t->input_regs as the authoritative cache

static mb_cmd_handler_t *get_command_handler(void);
mb_command_t            *get_command_instance(void);


// 输入寄存器同步接口
void mb_sync_running_status_reg(PmRunningState state)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return;
    mb->input_regs[INPUT_REG_DEV_RUNNING_STATE] = state;
}

void mb_sync_exception_reg(uint32_t exception, bool set)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return;
    if (set)
    {
        /* ALARM_STATUS occupies two registers (U32). We store as little-endian word pair
         * INPUT_REG_ALARM_STATUS = high-word? choose big-endian ordering consistent with docs.
         * Here we pack into two 16-bit words: high 16 bits and low 16 bits.
         */
        uint32_t cur = ((uint32_t)mb->input_regs[INPUT_REG_ALARM_STATUS] << 16)
                       | (uint32_t)mb->input_regs[INPUT_REG_ALARM_STATUS + 1];
        cur                                        |= exception;
        mb->input_regs[INPUT_REG_ALARM_STATUS]      = (uint16_t)((cur >> 16) & 0xFFFF);
        mb->input_regs[INPUT_REG_ALARM_STATUS + 1]  = (uint16_t)(cur & 0xFFFF);
    }
    else
    {
        uint32_t cur = ((uint32_t)mb->input_regs[INPUT_REG_ALARM_STATUS] << 16)
                       | (uint32_t)mb->input_regs[INPUT_REG_ALARM_STATUS + 1];
        cur                                        &= ~exception;
        mb->input_regs[INPUT_REG_ALARM_STATUS]      = (uint16_t)((cur >> 16) & 0xFFFF);
        mb->input_regs[INPUT_REG_ALARM_STATUS + 1]  = (uint16_t)(cur & 0xFFFF);
    }
}

// 新增：同步实时温度到底层输入寄存器（ABCD顺序，2寄存器）
void mb_sync_realtime_temp(float temperature)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return;
    uint16_t reg_h, reg_l;
    et_float_to_mb_abcd(temperature, &reg_h, &reg_l);
    if (mb->input_lock != RT_NULL)
        rt_mutex_take(mb->input_lock, RT_WAITING_FOREVER);
    mb->input_regs[INPUT_REG_REAL_TEMP_H] = reg_h;
    mb->input_regs[INPUT_REG_REAL_TEMP_L] = reg_l;
    if (mb->input_lock != RT_NULL)
        rt_mutex_release(mb->input_lock);
}

// 新增：同步实时旋光度到底层输入寄存器（ABCD顺序，2寄存器）
void mb_sync_realtime_rotation(float rotation)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return;
    uint16_t reg_h, reg_l;
    et_float_to_mb_abcd(rotation, &reg_h, &reg_l);
    if (mb->input_lock != RT_NULL)
        rt_mutex_take(mb->input_lock, RT_WAITING_FOREVER);
    mb->input_regs[INPUT_REG_REAL_ROT_H] = reg_h;
    mb->input_regs[INPUT_REG_REAL_ROT_L] = reg_l;
    if (mb->input_lock != RT_NULL)
        rt_mutex_release(mb->input_lock);
}

// 新增：同步测量结果（模式、数值、温度）到底层输入寄存器
void mb_sync_result(uint8_t mode, float value, float temp)
{
    uint16_t      reg_h, reg_l;
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return;
    if (mb->input_lock != RT_NULL)
        rt_mutex_take(mb->input_lock, RT_WAITING_FOREVER);
    mb->input_regs[INPUT_REG_RESULT_MODE] = mode;
    et_float_to_mb_abcd(value, &reg_h, &reg_l);
    mb->input_regs[INPUT_REG_RESULT_VAL_H] = reg_h;
    mb->input_regs[INPUT_REG_RESULT_VAL_L] = reg_l;
    et_float_to_mb_abcd(temp, &reg_h, &reg_l);
    mb->input_regs[INPUT_REG_RESULT_TEMP_H] = reg_h;
    mb->input_regs[INPUT_REG_RESULT_TEMP_L] = reg_l;
    if (mb->input_lock != RT_NULL)
        rt_mutex_release(mb->input_lock);
}

void mb_sync_meas_done_flag(bool done)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return;
    if (mb->input_lock != RT_NULL)
        rt_mutex_take(mb->input_lock, RT_WAITING_FOREVER);
    mb->input_regs[INPUT_REG_MEAS_DONE_FLAG] = done ? 1 : 0;
    if (mb->input_lock != RT_NULL)
        rt_mutex_release(mb->input_lock);
}
// 处理保持寄存器写入
nmbs_error mb_handle_write_holding_registers(uint16_t address, uint16_t quantity, const uint16_t *registers)
{
    mb_command_t     *mb_cmd  = get_command_instance();
    mb_cmd_handler_t *handler = get_command_handler();
    if (mb_cmd == NULL || handler == NULL)
    {
        ET_ERR("mb command instance failed");
        return NMBS_EXCEPTION_SERVER_DEVICE_FAILURE;
    }

    switch (address)
    {
    case HOLD_REG_SYS_CTRL_CMD: // 系统控制命令（30001）
        if (quantity != 1)
        {
            ET_ERR("HOLD_REG_SYS_CTRL_CMD quantity error, expect 1, got %d", quantity);
            return NMBS_ERROR_INVALID_REQUEST;
        }

        if (handler->system_ctrl_handler)
        {
            handler->system_ctrl_handler(registers[0]);
        }
        mb_cmd->regs[address] = registers[0] & 0xFF;
        return NMBS_ERROR_NONE;

    case HOLD_REG_MEAS_MODE: // 测量模式设置（30002）
        if (quantity != 1)
        {
            ET_ERR("HOLD_REG_MEAS_MODE quantity error, expect 1, got %d", quantity);
            return NMBS_ERROR_INVALID_REQUEST;
        }
        mb_cmd->regs[address] = registers[0] & 0xFF; // 取低8位,写入底层寄存器
        ET_INFO("Measurement mode set to: %d", mb_cmd->regs[address]);

        if (handler->meas_mode_handler)
        {
            handler->meas_mode_handler(mb_cmd->regs[address]);
        }
        return NMBS_ERROR_NONE;

    case HOLD_REG_TARGET_TEMP_H: // 目标温度设置（30003-30004）
        if (quantity != 2)
        {
            ET_ERR("HOLD_REG_TARGET_TEMP_H quantity error, expect 2, got %d", quantity);
            return NMBS_ERROR_INVALID_REQUEST;
        }
        float target_temp = et_mb_to_float_abcd(registers[0], registers[1]);

        // 温度范围检查（-10℃ ~ 100℃）
        if (target_temp > PM_TARGET_TEMP_MAX || target_temp < PM_TARGET_TEMP_MIN)
        {
            ET_ERR("HOLD_REG_TARGET_TEMP_H value error, expect:[%.2f~%.2f], got %.2f", PM_TARGET_TEMP_MIN,
                   PM_TARGET_TEMP_MAX, target_temp);
            return NMBS_EXCEPTION_ILLEGAL_DATA_VALUE;
        }
        if (handler->target_temp_handler)
        {
            handler->target_temp_handler(target_temp);
        }

        // 写入底层寄存器（高16位和低16位）
        mb_cmd->regs[address]     = registers[0];
        mb_cmd->regs[address + 1] = registers[1];
        ET_INFO("Target temperature set to: %.1f deg", target_temp);

        // send temperature update event
        if (tec_control && tec_control->control_event)
        {
            rt_event_send(tec_control->control_event, TEC_TEMP_UPDATE_EVENT);
        }
        ET_WARN("[MB] RX Target Temp: %.2f C", target_temp);
        return NMBS_ERROR_NONE;
    case HOLD_REG_TARGET_TEMP_L: // // 低16位单独写入时拒绝（需通过高地址写入2个寄存器）
        ET_ERR("[MB] RX Target Temp Low, Rejected");
        return NMBS_ERROR_INVALID_REQUEST;

    case HOLD_REG_TUBE_LEN: // 旋光管长度设置（30005-30006）
        if (quantity != 1)
        {
            ET_ERR("[MB] RX HOLD_REG_TUBE_LEN quantity error, expect 2, got %d", quantity);
            return NMBS_ERROR_INVALID_REQUEST;
        }
        uint16_t tube_length = registers[0];

        // 检查旋光管长度是否有效（>0）
        if (tube_length < PM_TUBE_LENGTH_MIN || tube_length > PM_TUBE_LENGTH_MAX)
        {
            ET_ERR("[MB] RX tube length value error, expect:[%d~%d], got %d", PM_TUBE_LENGTH_MIN, PM_TUBE_LENGTH_MAX,
                   tube_length);
            return NMBS_EXCEPTION_ILLEGAL_DATA_VALUE; // 对应Modbus异常0x03
        }
        if (handler->tube_length_handler)
        {
            handler->tube_length_handler(tube_length);
        }
        // 写入底层寄存器（高16位和低16位）
        mb_cmd->regs[address] = registers[0];
        ET_INFO("Tube length set to: %d mm", tube_length);
        return NMBS_ERROR_NONE;

    case HOLD_REG_MEAS_PRECISION: // 测量精度设置（30007）
        if (quantity != 1)
        {
            ET_ERR("[MB] RX HOLD_REG_MEAS_PRECISION value error, must write one register");
            return NMBS_ERROR_INVALID_REQUEST;
        }
        uint8_t measure_precision = registers[0] & 0xFF;
        if (handler->meas_precision_handler)
        {
            handler->meas_precision_handler(measure_precision);
        }
        // 写入底层寄存器
        mb_cmd->regs[address] = measure_precision;
        ET_INFO("Measure precision set to: %d", measure_precision);

        return NMBS_ERROR_NONE;

    case HOLD_REG_AUTO_MEAS_CNT: // 自动测量次数（30008）
        if (quantity != 1)
        {
            ET_ERR("Auto measure count write error: %d", registers[0]);
            return NMBS_ERROR_INVALID_REQUEST;
        }
        float auto_measure_count = registers[0] & 0xFF;
        if (handler->auto_measure_count_handler)
        {
            handler->auto_measure_count_handler(auto_measure_count);
        }
        if (auto_measure_count == 0)
        {
            ET_ERR("Auto measure count write error: %d", auto_measure_count);
            return NMBS_ERROR_INVALID_REQUEST; // 次数不能为0（0x01错误）
        }
        // 写入底层寄存器
        mb_cmd->regs[address] = auto_measure_count;
        ET_INFO("Auto measure count set to: %d", auto_measure_count);
        return NMBS_ERROR_NONE;

    case HOLD_REG_HIST_QUERY_START: // 历史数据查询范围（30009-30010）
        if (quantity != 2)
        {
            ET_ERR("History query start error, quantity error, expect 2, got %d", quantity);
            return NMBS_ERROR_INVALID_REQUEST;
        }
        uint8_t history_start = registers[0];
        uint8_t history_count = registers[1];

        // 检查历史数据范围有效性
        if (history_count == 0 || history_count > 5)
        {
            ET_ERR("History query count error, expect 1-5, got %d", history_count);
            return NMBS_EXCEPTION_ILLEGAL_DATA_VALUE; // 对应Modbus异常0x03
        }

        ET_INFO("History query range set: start=%d, count=%d", history_start, history_count);
        return NMBS_ERROR_NONE;

    default:
        return NMBS_ERROR_INVALID_REQUEST;
    }
    return NMBS_EXCEPTION_SERVER_DEVICE_FAILURE;
}

// 处理输入寄存器读取
nmbs_error mb_handle_read_input_registers(uint16_t address, uint16_t quantity, uint16_t *registers_out)
{
    mb_command_t *mb = get_command_instance();
    if (!mb)
        return NMBS_EXCEPTION_SERVER_DEVICE_FAILURE;

    if (address + quantity > 0x0029)
        return NMBS_ERROR_INVALID_REQUEST;

    for (uint16_t i = 0; i < quantity;)
    {
        uint16_t curr_addr = address + i;
        switch (curr_addr)
        {
        case INPUT_REG_REAL_TEMP_H:
        {
            if (mb->input_lock != RT_NULL)
                rt_mutex_take(mb->input_lock, RT_WAITING_FOREVER);
            registers_out[i++] = mb->input_regs[INPUT_REG_REAL_TEMP_H];
            if (i < quantity)
                registers_out[i++] = mb->input_regs[INPUT_REG_REAL_TEMP_L];
            if (mb->input_lock != RT_NULL)
                rt_mutex_release(mb->input_lock);
            ET_DBG("Send real temp high: 0x%x low: 0x%x", mb->input_regs[INPUT_REG_REAL_TEMP_H],
                   mb->input_regs[INPUT_REG_REAL_TEMP_L]);
            break;
        }
        case INPUT_REG_REAL_ROT_H:
        {
            if (mb->input_lock != RT_NULL)
                rt_mutex_take(mb->input_lock, RT_WAITING_FOREVER);
            registers_out[i++] = mb->input_regs[INPUT_REG_REAL_ROT_H];
            if (i < quantity)
                registers_out[i++] = mb->input_regs[INPUT_REG_REAL_ROT_L];
            if (mb->input_lock != RT_NULL)
                rt_mutex_release(mb->input_lock);
            ET_DBG("Send real rot high: 0x%x low: 0x%x", mb->input_regs[INPUT_REG_REAL_ROT_H],
                   mb->input_regs[INPUT_REG_REAL_ROT_L]);
            break;
        }
        case INPUT_REG_RESULT_MODE:
            registers_out[i++] = mb->input_regs[INPUT_REG_RESULT_MODE];
            ET_DBG("Send result val high: 0x%x low: 0x%x", mb->input_regs[INPUT_REG_RESULT_VAL_H],
                   mb->input_regs[INPUT_REG_RESULT_VAL_L]);
            break;
        case INPUT_REG_RESULT_VAL_H:
        {
            if (mb->input_lock != RT_NULL)
                rt_mutex_take(mb->input_lock, RT_WAITING_FOREVER);
            registers_out[i++] = mb->input_regs[INPUT_REG_RESULT_VAL_H];
            if (i < quantity)
                registers_out[i++] = mb->input_regs[INPUT_REG_RESULT_VAL_L];
            if (mb->input_lock != RT_NULL)
                rt_mutex_release(mb->input_lock);
            ET_DBG("Send result val high: 0x%x low: 0x%x", mb->input_regs[INPUT_REG_RESULT_VAL_H],
                   mb->input_regs[INPUT_REG_RESULT_VAL_L]);
            break;
        }
        case INPUT_REG_RESULT_TEMP_H:
        {
            if (mb->input_lock != RT_NULL)
                rt_mutex_take(mb->input_lock, RT_WAITING_FOREVER);
            registers_out[i++] = mb->input_regs[INPUT_REG_RESULT_TEMP_H];
            if (i < quantity)
                registers_out[i++] = mb->input_regs[INPUT_REG_RESULT_TEMP_L];
            if (mb->input_lock != RT_NULL)
                rt_mutex_release(mb->input_lock);
            ET_DBG("Send result temp high: 0x%x low: 0x%x", mb->input_regs[INPUT_REG_RESULT_TEMP_H],
                   mb->input_regs[INPUT_REG_RESULT_TEMP_L]);
            break;
        }
        case INPUT_REG_DEV_RUNNING_STATE:
            registers_out[i++] = mb->input_regs[INPUT_REG_DEV_RUNNING_STATE];
            ET_DBG("Send device running state: %d", mb->input_regs[INPUT_REG_DEV_RUNNING_STATE]);
            break;
        case INPUT_REG_ALARM_STATUS:
        {
            /* Output two registers (high then low) representing 32-bit alarm bitmap */
            registers_out[i++] = mb->input_regs[INPUT_REG_ALARM_STATUS];
            if (i < quantity)
                registers_out[i++] = mb->input_regs[INPUT_REG_ALARM_STATUS + 1];
            ET_DBG("Send alarm status high: 0x%x low: 0x%x", mb->input_regs[INPUT_REG_ALARM_STATUS],
                   mb->input_regs[INPUT_REG_ALARM_STATUS + 1]);
            break;
        }
        case INPUT_REG_MEAS_DONE_FLAG:
            registers_out[i++] = mb->input_regs[INPUT_REG_MEAS_DONE_FLAG];
            ET_DBG("Send meas done flag: %d", mb->input_regs[INPUT_REG_MEAS_DONE_FLAG]);
            break;
        case INPUT_REG_DEVICE_MODEL_H:
            registers_out[i++] = mb->input_regs[INPUT_REG_DEVICE_MODEL_H];
            ET_DBG("Send device model high: 0x%x", mb->input_regs[INPUT_REG_DEVICE_MODEL_H]);
            break;
        case INPUT_REG_DEVICE_MODEL_L:
            registers_out[i++] = mb->input_regs[INPUT_REG_DEVICE_MODEL_L];
            ET_DBG("Send device model low: 0x%x", mb->input_regs[INPUT_REG_DEVICE_MODEL_L]);
            break;
        case INPUT_REG_FW_VERSION_H:
            registers_out[i++] = mb->input_regs[INPUT_REG_FW_VERSION_H];
            ET_DBG("Send firmware version high: 0x%x", mb->input_regs[INPUT_REG_FW_VERSION_H]);
            break;
        case INPUT_REG_FW_VERSION_L:
            registers_out[i++] = mb->input_regs[INPUT_REG_FW_VERSION_L];
            ET_DBG("Send firmware version low: 0x%x", mb->input_regs[INPUT_REG_FW_VERSION_L]);
            break;
        default:
                return NMBS_ERROR_INVALID_REQUEST;
        }
    }
    return NMBS_ERROR_NONE;
}


mb_cmd_handler_t *get_command_handler(void)
{
    return cmd_handler;
}

mb_command_t *get_command_instance(void)
{
    return mb_cmd;
}


// 初始化命令模块
void mb_command_init(mb_command_t *cmd)
{
    cmd_handler = cmd->handler;
    mb_cmd      = cmd;
    /* create mutex for protecting input_regs (ignore if already created) */
    if (mb_cmd->input_lock == RT_NULL)
    {
        mb_cmd->input_lock = rt_mutex_create("mb_in_lk", RT_IPC_FLAG_PRIO);
    }
}
