#include "battery.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
#include "esp_log.h"
#include "esp_check.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_lvgl_port.h"
#include "../ui/battery_ui.h"
#include <stdio.h>

static const char *TAG = "BAT";

// ADC句柄
static adc_oneshot_unit_handle_t adc_handle = NULL;
static adc_cali_handle_t cali_handle = NULL;
static bool cali_enabled = false;

// 当前电池数据
static uint32_t bat_voltage_mv = 0;
static uint8_t bat_level = 0;

// 锂电池放电曲线查找表（基于典型3.7V单节锂电池放电特性）
// 电压单位：毫伏，电量单位：百分比
typedef struct {
    uint16_t voltage_mv;
    uint8_t level;
} bat_curve_point_t;

static const bat_curve_point_t bat_curve[] = {
    {4200, 100},
    {4150,  95},
    {4110,  90},
    {4080,  85},
    {4020,  80},
    {3980,  75},
    {3950,  70},
    {3910,  65},
    {3870,  60},
    {3840,  55},
    {3800,  50},
    {3760,  45},
    {3730,  40},
    {3700,  35},
    {3680,  30},
    {3650,  25},
    {3630,  20},
    {3600,  15},
    {3570,  10},
    {3530,   5},
    {3400,   2},
    {3000,   0},
};

#define BAT_CURVE_SIZE (sizeof(bat_curve) / sizeof(bat_curve[0]))

// 电压转电量（线性插值，提高精度）
static uint8_t voltage_to_level(uint32_t voltage_mv)
{
    // 超出上限
    if (voltage_mv >= bat_curve[0].voltage_mv) {
        return 100;
    }
    // 低于下限
    if (voltage_mv <= bat_curve[BAT_CURVE_SIZE - 1].voltage_mv) {
        return 0;
    }
    // 在查找表中线性插值
    for (int i = 0; i < BAT_CURVE_SIZE - 1; i++) {
        if (voltage_mv >= bat_curve[i + 1].voltage_mv) {
            uint32_t v_range = bat_curve[i].voltage_mv - bat_curve[i + 1].voltage_mv;
            uint32_t l_range = bat_curve[i].level - bat_curve[i + 1].level;
            uint32_t v_offset = voltage_mv - bat_curve[i + 1].voltage_mv;
            return bat_curve[i + 1].level + (uint8_t)((v_offset * l_range) / v_range);
        }
    }
    return 0;
}

// 初始化ADC校准
static void battery_cali_init(void)
{
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
    // ESP32-S3 使用曲线拟合校准
    adc_cali_curve_fitting_config_t cali_cfg = {
        .unit_id = ADC_UNIT_1,
        .chan = BAT_ADC_CHANNEL,
        .atten = ADC_ATTEN_DB_11,
        .bitwidth = ADC_BITWIDTH_DEFAULT,
    };
    esp_err_t ret = adc_cali_create_scheme_curve_fitting(&cali_cfg, &cali_handle);
#elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
    // 备用：线性拟合校准
    adc_cali_line_fitting_config_t cali_cfg = {
        .unit_id = ADC_UNIT_1,
        .atten = ADC_ATTEN_DB_11,
        .bitwidth = ADC_BITWIDTH_DEFAULT,
    };
    esp_err_t ret = adc_cali_create_scheme_line_fitting(&cali_cfg, &cali_handle);
#else
    esp_err_t ret = ESP_ERR_NOT_SUPPORTED;
#endif
    if (ret == ESP_OK) {
        cali_enabled = true;
        ESP_LOGI(TAG, "ADC校准初始化成功");
    } else {
        ESP_LOGW(TAG, "ADC校准不可用，将使用原始值换算");
    }
}

esp_err_t battery_init(void)
{
    // 初始化ADC单元
    adc_oneshot_unit_init_cfg_t unit_cfg = {
        .unit_id = ADC_UNIT_1,
        .ulp_mode = ADC_ULP_MODE_DISABLE,
    };
    ESP_RETURN_ON_ERROR(adc_oneshot_new_unit(&unit_cfg, &adc_handle),
                        TAG, "ADC单元初始化失败");

    // 配置ADC通道（11dB衰减，量程约0~2500mV）
    adc_oneshot_chan_cfg_t chan_cfg = {
        .atten = ADC_ATTEN_DB_11,
        .bitwidth = ADC_BITWIDTH_DEFAULT,
    };
    ESP_RETURN_ON_ERROR(adc_oneshot_config_channel(adc_handle, BAT_ADC_CHANNEL, &chan_cfg),
                        TAG, "ADC通道配置失败");

    // 初始化校准
    battery_cali_init();

    ESP_LOGI(TAG, "电池ADC初始化完成 (GPIO%d, ADC1_CH%d, 分压比=%d)",
             PIN_BAT_ADC, BAT_ADC_CHANNEL, BAT_VOLTAGE_DIVIDER);
    return ESP_OK;
}

uint32_t battery_get_voltage_mv(void)
{
    return bat_voltage_mv;
}

uint8_t battery_get_level(void)
{
    return bat_level;
}

// 读取ADC并计算电池电压和电量
static void battery_read(void)
{
    int adc_sum = 0;
    int valid_count = 0;

    // 多次采样取平均，滤除噪声
    for (int i = 0; i < BAT_SAMPLE_COUNT; i++) {
        int raw;
        if (adc_oneshot_read(adc_handle, BAT_ADC_CHANNEL, &raw) == ESP_OK) {
            adc_sum += raw;
            valid_count++;
        }
        vTaskDelay(pdMS_TO_TICKS(2));
    }

    if (valid_count == 0) {
        ESP_LOGE(TAG, "ADC采样全部失败");
        return;
    }

    int adc_avg = adc_sum / valid_count;

    // 使用校准值或原始换算得到ADC引脚电压
    int adc_voltage_mv = 0;
    if (cali_enabled) {
        adc_cali_raw_to_voltage(cali_handle, adc_avg, &adc_voltage_mv);
    } else {
        // 无校准时按3300mV参考电压线性换算
        adc_voltage_mv = (adc_avg * 3300) / 4095;
    }

    // 乘以分压系数得到实际电池电压
    bat_voltage_mv = (uint32_t)adc_voltage_mv * BAT_VOLTAGE_DIVIDER;

    // 查找表+插值计算电量百分比
    bat_level = voltage_to_level(bat_voltage_mv);

    ESP_LOGI(TAG, "ADC原始值=%d, ADC电压=%dmV, 电池电压=%lumV, 电量=%d%%",
             adc_avg, adc_voltage_mv, (unsigned long)bat_voltage_mv, bat_level);
}

// 更新UI电量显示（线程安全）
static void battery_update_ui(void)
{
    if (!lvgl_port_lock(100)) {
        return;
    }

    // 更新所有界面的电池指示器
    battery_ui_update_level(bat_level);

    lvgl_port_unlock();
}

// 电池监控任务
static void battery_monitor_task(void *pvParameters)
{
    while (1) {
        battery_read();
        battery_update_ui();
        vTaskDelay(pdMS_TO_TICKS(BAT_MONITOR_INTERVAL_MS));
    }
}

void battery_monitor_start(void)
{
    xTaskCreate(battery_monitor_task, "bat_mon", 4096, NULL, 3, NULL);
    ESP_LOGI(TAG, "电池监控任务已启动，更新间隔%dms", BAT_MONITOR_INTERVAL_MS);
}
