#include "app_home_page.h"
#include "../ui/ui_manager.h"
#include "../ui/ui/ui_pages/ui_home_page.h"
#include "../service/service_home_page.h"
#include "../data/data_home_page.h"
#include "core/lvgl/lvgl.h"
#include <math.h>

/* ====================================================================================================================
 * 文件名称: app_home_page.c
 * 文件职责: 首页App层实现 - 事件处理，协调Service和UI，管理页面生命周期
 * 架构位置: APP层 (Controller)
 * ==================================================================================================================== */

/* 定时刷新配置宏 */
#define HP_REFRESH_PERIOD_MS   500U        /* 遥测数据刷新周期（毫秒） */
#define HP_TIME_REFRESH_PERIOD_MS   1000U        /* 时间刷新周期（毫秒） */
#define HP_VALUE_TOLERANCE      0.01f      /* 浮点数比较容差 */

/* 静态变量定义 */
static lv_task_t *s_hp_refresh_task = NULL;  /* LVGL定时器句柄 */
static lv_task_t *s_time_refresh_task = NULL;  /* 时间刷新定时器句柄 */
static HomePageRawData s_last_raw_data = {0};  /* 上一次遥测数据缓存 */

/**
 * @brief  将组类型转换为索引
 * @param  group  组类型
 * @return 索引值 0-4
 */
static uint8_t hp_group_to_index(HomePageGroupType group)
{
    switch (group)
    {
    case HP_GROUP_MCB:
        return 0;
    case HP_GROUP_LCB:
        return 1;
    case HP_GROUP_LOAD_I:
        return 2;
    case HP_GROUP_ZERO_I:
        return 3;
    case HP_GROUP_DEV_INFO:
        return 4;
    default:
        return 0;
    }
}

/* ============================================================================
 * 自动刷新功能实现
 *
 * 一、核心用途
 *    实现首页数据的自动刷新，无需用户操作即可更新显示内容。
 *
 * 二、双定时器架构
 *    - 数据定时器(500ms): 非设备信息组使用，刷新电压/电流等遥测数据
 *    - 时间定时器(1000ms): 设备信息组专用，仅刷新系统时间显示
 *    两定时器互斥工作，组切换时自动切换。
 *
 * 三、触发条件
 *    1. 当前页面必须是PAGE_HOME_PAGE（页面退出后定时器自动失效）
 *    2. 数据定时器额外检查：数据变化量 > 0.01（容差过滤）
 *
 * 四、关键变量
 *    s_hp_refresh_task    - 数据定时器句柄
 *    s_time_refresh_task  - 时间定时器句柄
 *    s_last_raw_data      - 上次遥测数据缓存（用于变化检测）
 *
 * 五、调用关系
 *    app_home_page_create()     → hp_start_auto_refresh() 或 hp_start_time_refresh()
 *    app_home_page_handle_event() → LEFT/RIGHT切换定时器，ENTER停止全部
 *    app_home_page_destroy()    → hp_stop_auto_refresh() + hp_stop_time_refresh()
 *
 * 六、异常处理
 *    - 重复创建防护：启动前检查句柄是否为NULL
 *    - 页外回调防护：回调函数首行检查ui_manager_get_curpage()
 *    - 内存泄漏防护：stop时删除任务并置NULL，destroy时调用全部stop
 *
 * ============================================================================ */

/* 前置声明 */
static bool hp_data_changed(const HomePageRawData *current);
static void hp_update_cache(const HomePageRawData *current);
static void hp_time_refresh_timer_cb(lv_task_t *task);
static void hp_start_time_refresh(void);
static void hp_stop_time_refresh(void);

/**
 * @brief LVGL定时器回调函数
 * @param task LVGL任务句柄（未使用但保留接口）
 * @note 在LVGL任务上下文中执行，可直接操作UI
 */
static void hp_refresh_timer_cb(lv_task_t *task)
{
    // printf("%s called!\n", __FUNCTION__);
    (void)task;

    if (ui_manager_get_curpage() != PAGE_HOME_PAGE) {
        return;
    }

    HomePageRawData raw_data;
    if (!data_home_page_get_raw(&raw_data)) {
        return;
    }

    if (!hp_data_changed(&raw_data)) {
        return;
    }

    hp_update_cache(&raw_data);

    HomePageViewConfig config;
    HomePageGroupType current_group = home_page_service_get_current_group();

    if (home_page_service_get_config(current_group, &config)) {
        home_page_ui_refresh(&config);
    }
}

/**
 * @brief 启动自动刷新定时器
 * @note 页面创建时调用，避免重复创建
 */
static void hp_start_auto_refresh(void)
{
    if (s_hp_refresh_task != NULL) {
        return;
    }

    printf("%s create task!\n", __FUNCTION__);
    s_hp_refresh_task = lv_task_create(hp_refresh_timer_cb,
                                       HP_REFRESH_PERIOD_MS,
                                       LV_TASK_PRIO_LOW,
                                       NULL);
}

/**
 * @brief 停止自动刷新定时器
 * @note 页面退出时调用，防止内存泄漏
 */
static void hp_stop_auto_refresh(void)
{
    printf("%s stop auto refresh task!\n", __FUNCTION__);
    if (s_hp_refresh_task != NULL) {
        lv_task_del(s_hp_refresh_task);
        s_hp_refresh_task = NULL;
    }
}

/**
 * @brief 时间刷新LVGL定时器回调
 * @param task LVGL任务句柄
 * @note 仅在设备信息组时更新时间显示
 */
static void hp_time_refresh_timer_cb(lv_task_t *task)
{
    (void)task;

    if (ui_manager_get_curpage() != PAGE_HOME_PAGE) {
        return;
    }

    HomePageGroupType current_group = home_page_service_get_current_group();
    if (current_group != HP_GROUP_DEV_INFO) {
        return;
    }

    HomePageViewConfig config;
    if (home_page_service_get_config(current_group, &config)) {
        home_page_ui_refresh(&config);
    }
}

/**
 * @brief 启动时间刷新定时器
 * @note 仅在设备信息组时使用
 */
static void hp_start_time_refresh(void)
{
    if (s_time_refresh_task != NULL) {
        return;
    }

    printf("%s create task!\n", __FUNCTION__);
    s_time_refresh_task = lv_task_create(hp_time_refresh_timer_cb,
                                         HP_TIME_REFRESH_PERIOD_MS,
                                         LV_TASK_PRIO_LOW,
                                         NULL);
}

/**
 * @brief 停止时间刷新定时器
 */
static void hp_stop_time_refresh(void)
{
    printf("%s stop time refresh task!\n", __FUNCTION__);
    if (s_time_refresh_task != NULL) {
        lv_task_del(s_time_refresh_task);
        s_time_refresh_task = NULL;
    }
}

/**
 * @brief 检查数据是否有变化
 * @param current 当前数据
 * @return true-有变化, false-无变化
 * @note 使用容差比较浮点数，避免微小抖动导致频繁刷新
 */
static bool hp_data_changed(const HomePageRawData *current)
{
    for (uint8_t i = 0; i < HP_TELEMET_NUM; i++) {
        float diff = fabs(current->telemet[i].value - s_last_raw_data.telemet[i].value);
        if (diff > HP_VALUE_TOLERANCE) {
            return true;
        }
    }
    return false;
}

/**
 * @brief 更新缓存数据
 * @param current 当前数据
 */
static void hp_update_cache(const HomePageRawData *current)
{
    s_last_raw_data = *current;
}

void app_home_page_create(void)
{
    /* 初始化Service层 */
    home_page_service_init();
    
    /* 初始化缓存数据 */
    data_home_page_get_raw(&s_last_raw_data);
    
    /* 获取当前组配置 */
    HomePageViewConfig config;
    HomePageGroupType current_group = home_page_service_get_current_group();
    
    if (home_page_service_get_config(current_group, &config))
    {
        /* 创建UI */
        home_page_ui_create(&config);
    }

    /* 根据当前组启动对应的定时器 */
    if (current_group == HP_GROUP_DEV_INFO) {
        hp_start_time_refresh();
    } else {
        hp_start_auto_refresh();
    }
}

void app_home_page_handle_event(keyValue kval)
{
    HomePageGroupType new_group;
    HomePageViewConfig config;
    
    switch (kval)
    {
    case KEY_DATA_RIGHT:
        /* 切换到下一组 */
        new_group = home_page_service_next_group();
        
        /* 重置缓存，确保新组数据能立即显示 */
        data_home_page_get_raw(&s_last_raw_data);
        
        /* 获取新配置并刷新UI */
        if (home_page_service_get_config(new_group, &config))
        {
            home_page_ui_refresh(&config);
        }
        
        /* 切换定时器 */
        if (new_group == HP_GROUP_DEV_INFO) {
            hp_stop_auto_refresh();
            hp_start_time_refresh();
        } else {
            hp_stop_time_refresh();
            hp_start_auto_refresh();
        }
        break;
        
    case KEY_DATA_LEFT:
        /* 切换到上一组 */
        new_group = home_page_service_prev_group();
        
        /* 重置缓存，确保新组数据能立即显示 */
        data_home_page_get_raw(&s_last_raw_data);
        
        /* 获取新配置并刷新UI */
        if (home_page_service_get_config(new_group, &config))
        {
            home_page_ui_refresh(&config);
        }
        
        /* 切换定时器 */
        if (new_group == HP_GROUP_DEV_INFO) {
            hp_stop_auto_refresh();
            hp_start_time_refresh();
        } else {
            hp_stop_time_refresh();
            hp_start_auto_refresh();
        }
        break;
        
    case KEY_DATA_ENTER:
        /* 切换到主菜单前先停止所有定时器 */
        hp_stop_auto_refresh();
        hp_stop_time_refresh();
        /* 切换到主菜单 */
        ui_manager_switch_to_main_menu(0);
        break;
        
    default:
        break;
    }
}

void app_home_page_destroy(void)
{
    /* 停止所有定时器 */
    hp_stop_auto_refresh();
    hp_stop_time_refresh();
    /* 销毁UI */
    home_page_ui_destroy();
}

uint8_t app_home_page_get_current_group_index(void)
{
    return hp_group_to_index(home_page_service_get_current_group());
}
