/**
 * @file mdev_product_test
 * @author www.tuya.com
 * @version 0.1
 * @date 2023-09-28
 *
 * @copyright Copyright (c) tuya.inc 2023
 *
 */
#include "tuya_iot_config.h"
#include "tal_log.h"
#include "prod_test.h"

#include "tuya_devos_utils.h"
#include "ws_db_gw.h"
/***********************************************************
*********************** macro define ***********************
***********************************************************/
#ifndef USER_SW_VER
#define USER_SW_VER  "1.2.3"
#endif

#define APP_WF_CFG_MTHD                    GWCM_SPCL_AUTOCFG // GWCM_LOW_POWER//GWCM_SPCL_AUTOCFG //GWCM_LOW_POWER 

#define PRODUCT_TEST_WIFI_1                 "tuya_mdev_test1"
// #define PRODUCT_TEST_WIFI_2                 "tuya_mdev_test2"

#define PROD_TEST_WEAK_SIGNAL               -60
prodtest_ssid_info_t *ap_tmp_buf = NULL;
/***********************************************************
********************** typedef define **********************
***********************************************************/
typedef UCHAR_T PRODUCT_TEST_TYPE_E;
#define PRODUCT_TEST_TP_AGING          0x00
#define PRODUCT_TEST_TP_FUNCTION       0x01


typedef enum {
    MTST_NONE =0,                //
    MTST_RSSI_FAULT =1,        //RSSI < 60
    MTST_UNAUTH =2,       // unauth
    MTST_PRESS_WAIT,                 // wait press key.
    MTST_PRESS,                // handleing press.
    
    // MTST_
}MTST_STATUS_T;
/***********************************************************
********************** variable define *********************
***********************************************************/
STATIC CONST CHAR_T *cWIFI_SCAN_SSID_LIST[] = {
    PRODUCT_TEST_WIFI_1, 
    // PRODUCT_TEST_WIFI_2, 
};


STATIC BOOL_T                sg_is_aging_test_finish = FALSE;
STATIC BOOL_T                _mdev_in_test = FALSE;
STATIC PRODUCT_TEST_TYPE_E   sg_product_test_type = PRODUCT_TEST_TP_AGING;
STATIC MTST_STATUS_T _mtst_status = MTST_NONE;

/***********************************************************
********************** extern  define *********************
***********************************************************/
/**
 * @brief  Scan Wi-Fi test.
 *
 * @param[in] wf_cfg_mthd GW_WF_CFG_MTHD_SEL mode.
 * @param[in] ssid_list List of SSIDs to scan.
 * @param[in] ssid_count Count of SSIDs to scan.
 * @param[in] scan_info_cb Callback function to handle the scan result.
 *
 * @return BOOL_T TRUE if the scan is successful, otherwise FALSE.
 */
extern BOOL_T ty_scan_test_wifi(GW_WF_CFG_MTHD_SEL wf_cfg_mthd, CONST CHAR_T **ssid_list, \
                                UINT8_T ssid_count, prodtest_app_cb_t scan_info_cb);



/***********************************************************
********************** extern  define *********************
***********************************************************/
/**
 * @brief  Scan Wi-Fi test.
 *
 * @param[in] wf_cfg_mthd GW_WF_CFG_MTHD_SEL mode.
 * @param[in] ssid_list List of SSIDs to scan.
 * @param[in] ssid_count Count of SSIDs to scan.
 * @param[in] scan_info_cb Callback function to handle the scan result.
 *
 * @return BOOL_T TRUE if the scan is successful, otherwise FALSE.
 */


STATIC BOOL_T __is_allowed_scan_wifi_test(GW_WF_CFG_MTHD_SEL gwcm_mode)
{
    BOOL_T mf_close = FALSE;
    GW_WORK_STAT_MAG_S read_gw_wsm = {0};

    mf_close = mf_test_is_timeout();
    if (TRUE == mf_close) {
        TAL_PR_NOTICE("have actived over 15min, don't scan prod test ssid");
        return FALSE;
    }  
	
	if(GWCM_OLD == gwcm_mode) {          
        return FALSE;
    }

    wd_gw_wsm_read(&read_gw_wsm);
    if ((gwcm_mode == GWCM_OLD_PROD) || (gwcm_mode == GWCM_LOW_POWER_AUTOCFG) ||
        (gwcm_mode == GWCM_SPCL_AUTOCFG)) { /* 上电默认配网或者第一次是配网的模式 */
          if (((read_gw_wsm.nc_tp >= GWNS_TY_SMARTCFG) && (read_gw_wsm.nc_tp != GWNS_UNCFG_SMC_AP) && (read_gw_wsm.nc_tp != GWNS_OTHER_UNCFG)) || read_gw_wsm.md > GWM_NORMAL) { /* 已经存在ssid等配网信息但是并不是EZ和AP共存配网 */
            return FALSE;
        }
    } else if (gwcm_mode == GWCM_SPCL_MODE || gwcm_mode == GWCM_LOW_POWER) { /* 上电默认不配网 */
        if (read_gw_wsm.nc_tp >= GWNS_UNCFG_SMC) {                           /* 处于配网的状态 */
            return FALSE;
        }
    } else {
        ;
    }

    return TRUE;
}

/**
 * @brief Get target AP from scan AP.
 *
 * @param[in] ssid_list List of SSIDs to scan.
 * @param[in] ssid_count Count of SSIDs to scan.
 * @param[in] all_ap List of all APs.
 * @param[in] all_ap_num Number of all APs.
 * @param[out] target_ap Pointer to allocated memory containing target AP information.
 *
 * @return UINT_T Number of target APs.
 */
STATIC UINT_T __get_target_ap_from_all_ap(IN CONST CHAR_T **ssid_list, UINT8_T ssid_count,\
                                          AP_IF_S *all_ap, UINT_T all_ap_num,\
                                          OUT prodtest_ssid_info_t **target_ap)
{
    
    UINT_T i = 0, j =0 , target_ap_num = 0;
    BOOL_T  add_target_ap = FALSE;

    if(NULL == target_ap) {
        return 0;
    }

    //prepare ap info buf
    ap_tmp_buf = (prodtest_ssid_info_t *)tal_malloc(SIZEOF(prodtest_ssid_info_t) * ssid_count);
    if (NULL == ap_tmp_buf) {
        return 0;
    }
    memset(ap_tmp_buf, 0, SIZEOF(prodtest_ssid_info_t) * ssid_count);

    for (i = 0; i<ssid_count; i++) {
        for (j = 0; j < all_ap_num; j++) {
            if (0 != strcmp((char *)ssid_list[i], (char *)all_ap[j].ssid)) {  
                continue;
            }  

            //当前扫描到的ssid与扫描列表一致
            if (0 == strcmp((char *)ap_tmp_buf[target_ap_num].ssid, (char *)all_ap[j].ssid)) {
                //当前扫描到的ssid已存储,判断rssi是否需要更新
                if (all_ap[j].rssi > ap_tmp_buf[target_ap_num].rssi) {
                    TAL_PR_DEBUG("[update rssi] new:%d old:%d", all_ap[j].rssi, ap_tmp_buf[target_ap_num].rssi);
                    ap_tmp_buf[target_ap_num].rssi = all_ap[j].rssi;
                }
            }else {
                // 存储目标 ssid 信息
                add_target_ap = TRUE;
                strcpy((char *)ap_tmp_buf[target_ap_num].ssid, (char *)all_ap[j].ssid);
                ap_tmp_buf[target_ap_num].rssi = all_ap[j].rssi;
                TAL_PR_DEBUG("new index:%d ssid%s", target_ap_num, ap_tmp_buf[target_ap_num].ssid);
            }
        }


        if(TRUE == add_target_ap) {
            add_target_ap = FALSE;
            target_ap_num++;
        }
    }

    if(0 == target_ap_num) {
        tal_free(ap_tmp_buf), ap_tmp_buf = NULL;
        *target_ap = NULL;
    }else {
        *target_ap = ap_tmp_buf;
    }

    return target_ap_num;
}

/**
 * @brief Release target AP memory.
 *
 * @param[in] target_ap Pointer to the allocated memory containing target AP information.
 *
 * @return VOID_T.
 */
STATIC VOID_T __release_target_ap(prodtest_ssid_info_t *target_ap)
{
    if(target_ap) {
        tal_free(target_ap);
    }

    return;
}

/**
 * @brief  Scan Wi-Fi test.
 *
 * @param[in] wf_cfg_mthd GW_WF_CFG_MTHD_SEL mode.
 * @param[in] ssid_list List of SSIDs to scan.
 * @param[in] ssid_count Count of SSIDs to scan.
 * @param[in] scan_info_cb Callback function to handle the scan result.
 *
 * @return BOOL_T TRUE if the scan is successful, otherwise FALSE.
 */
BOOL_T ty_scan_test_wifi(GW_WF_CFG_MTHD_SEL wf_cfg_mthd, CONST CHAR_T **ssid_list, \
                         UINT8_T ssid_count, prodtest_app_cb_t scan_info_cb)
{
    OPERATE_RET ret = OPRT_OK;
    prodtest_ssid_info_t *target_ap = NULL;
    AP_IF_S *ap = NULL;
    UINT_T ap_num = 0, target_ap_num = 0;
    BOOL_T flag = TRUE;

    TAL_PR_NOTICE("ty_scan_test_wifi ssid count :  %d ", ssid_count);
    if (NULL == ssid_list || ssid_count == 0 || scan_info_cb == NULL) {
        return FALSE;
    }

    if(FALSE == __is_allowed_scan_wifi_test(wf_cfg_mthd)) {
        return FALSE;
    }
    //scan all ap
    tal_wifi_set_work_mode(WWM_STATION);
    ret = tal_wifi_all_ap_scan(&ap, &ap_num);
    tal_wifi_station_disconnect();
    if (OPRT_OK != ret || 0 == ap_num) {
        TAL_PR_NOTICE("tal_wifi_all_ap_scan failed(%d) ap_num(%d)", ret, ap_num);
        return FALSE;
    }

    //compare ssid information
    target_ap_num = __get_target_ap_from_all_ap(ssid_list, ssid_count, ap, ap_num, &target_ap);
    tal_wifi_release_ap(ap);
    ap = NULL, ap_num = 0;
    if(0 == target_ap_num) {
        TAL_PR_DEBUG("cant find target from scan result");
        return FALSE;
    }

    //check dev authorized
    flag = get_gw_auth_status();

    //clear gateway config flash data
    GW_WORK_STAT_MAG_S *wsm = (GW_WORK_STAT_MAG_S *)tal_malloc(SIZEOF(GW_WORK_STAT_MAG_S));
    if (NULL != wsm) {
        memset(wsm, 0, SIZEOF(GW_WORK_STAT_MAG_S));
        ret = wd_gw_wsm_write(wsm);
        if (OPRT_OK != ret) {
            TAL_PR_ERR("wd_gw_wsm_write err:%d!", ret);
        }
        tal_free(wsm);
    }

    ret = scan_info_cb(flag, target_ap, target_ap_num);

    __release_target_ap(target_ap);
    target_ap = NULL, target_ap_num = 0;

    return ((OPRT_OK == ret) ? TRUE : FALSE);
}



/***********************************************************
********************** function define *********************
***********************************************************/
STATIC prodtest_ssid_info_t *__ty_app_find_target_ssid(CHAR_T *target_ssid, prodtest_ssid_info_t *wifi_arr, UINT8_T arr_cnt)
{
    UINT8_T i = 0 ;

    if(NULL == target_ssid || NULL == wifi_arr || 0 == arr_cnt) {
        return NULL;
    }

    for(i = 0;  i<arr_cnt; i++) {
        TAL_PR_DEBUG("ssid:%s ", wifi_arr[i].ssid);
        if(0 == strcmp(wifi_arr[i].ssid, target_ssid)) {
            return &wifi_arr[i];
        }
    }

    return NULL;
}
bool mdev_in_testing(){
    return (TRUE == _mdev_in_test);
}

STATIC OPERATE_RET __scan_wifi_test_info_cb(INT_T flag, prodtest_ssid_info_t *ssid_info, UINT8_T info_count)
{
    prodtest_ssid_info_t *p_ssid_info = NULL;

    TAL_PR_DEBUG("__scan_wifi_test_info_cb:%p   !", ssid_info);
    //cant find target ssid 
    if(NULL == ssid_info) {
        return OPRT_COM_ERROR;
    }
    p_ssid_info = ssid_info;
    TAL_PR_DEBUG("rssi:%d   !", p_ssid_info->rssi);
    if(p_ssid_info->rssi < PROD_TEST_WEAK_SIGNAL) { //check signal
        TAL_PR_NOTICE("rssi:%d weak signal !", p_ssid_info->rssi);
        // todo: production signal is weak
        _mtst_status = MTST_RSSI_FAULT;
        return OPRT_OK;
    }
    
    TAL_PR_DEBUG("authorized flag:%d ", flag);
    if(0 == flag) { 
        //todo: device not authorized
        _mtst_status = MTST_UNAUTH; 
        return OPRT_OK;
    }
    
    if(PRODUCT_TEST_TP_AGING == sg_product_test_type){
        //todo: device aging test

    }else if(PRODUCT_TEST_TP_FUNCTION == sg_product_test_type) {
        //todo: device function test
    }
    _mtst_status = MTST_PRESS_WAIT;
    return OPRT_OK;
}

STATIC OPERATE_RET __user_product_test_cmd_cb(USHORT_T cmd, UCHAR_T *data, UINT_T len,\
                                              OUT UCHAR_T **ret_data, OUT USHORT_T *ret_len)
{
    //todo: process user product test command from production
    TAL_PR_DEBUG(" __user_product_test_cmd_cb!");
    return OPRT_OK;
}

/**
 * @brief Function that performs the product test.
 *
 * The function scans for Wi-Fi access points specified in cWIFI_SCAN_SSID_LIST
 * and performs the product test using the __scan_wifi_test_info_cb callback function.
 * If the scan is successful and the target SSID is found, the function proceeds with the appropriate product test. 
 * The function also registers the __user_product_test_cmd_cb callback
 * to process any user product test command received from production.
 *
 * @param[in] argc Number of arguments passed to the function.
 * @param[in] argv Array of arguments passed to the function.
 *
 * @return None.
 */ 
VOID mdev_product_test(INT_T argc, CHAR_T *argv[])
{
    TAL_PR_DEBUG("enter product  m !");
#if 0 //defined(ENABLE_PRODUCT_AUTOTEST) && (ENABLE_PRODUCT_AUTOTEST == 1)
    TAL_PR_DEBUG("ENABLE_PRODUCT_AUTOTEST 1 !");
    prodtest_app_cfg_t prodtest_cfg = {.gwcm_mode  = APP_WF_CFG_MTHD,
                                       .file_name  = APP_BIN_NAME,
                                       .file_ver   = USER_SW_VER,
                                       .ssid_list  = cWIFI_SCAN_SSID_LIST,
                                       .ssid_count = CNTSOF(cWIFI_SCAN_SSID_LIST),
                                       .app_cb     = __scan_wifi_test_info_cb,
                                       .product_cb = __user_product_test_cmd_cb};

    prodtest_app_register(&prodtest_cfg);

    // if (TRUE == prodtest_ssid_scan(500)) {
    
    if(TRUE == prodtest_ssid_scan(10000)) {
        //所有产测路由都要在6信道
        TAL_PR_NOTICE("enter product test !");
    }else{
        TAL_PR_NOTICE("notenter product test !");
    } 
#else 
    if(TRUE == ty_scan_test_wifi(APP_WF_CFG_MTHD, cWIFI_SCAN_SSID_LIST, \
                                 CNTSOF(cWIFI_SCAN_SSID_LIST), __scan_wifi_test_info_cb)) {

        TAL_PR_NOTICE("enter product test !");
    }else{
         TAL_PR_NOTICE("not enter product test !");
    }
#endif

    return;
}