#include "device_identity.h"
#include "device_wifi_change.h"
#include "modules_common.h"

char g_current_ssid[SSID_MAX_LEN] = {0};//用于存现在已连接WiFi
static char s_wifi_last_ssid[SSID_MAX_LEN]= {0} ;
static char s_wifi_last_password[SSID_MAX_LEN]= {0} ;

//获取当前连接wifi
void get_current_wifi() {
    g_current_ssid[0] = '\0';

    FILE *fp = popen("nmcli -t -f ACTIVE,SSID dev wifi", "r");
    if (!fp) {
        my_zlog_error("{\"error\": \"无法执行扫描命令\"}");
        return;
    }

    char line[256];
    while (fgets(line, sizeof(line), fp)) {
        char *active = strtok(line, ":");
        char *ssid = strtok(NULL, "\n");
        if (active && ssid && strcmp(active, "yes") == 0 && strlen(ssid) > 0) {
            strncpy(g_current_ssid, ssid, SSID_MAX_LEN - 1);
            g_current_ssid[SSID_MAX_LEN - 1] = '\0';
            break;
        }
    }
    pclose(fp);
}

//找重复的WiFi名称
int find_ssid(wifi_info_t list[], int count, const char *ssid) {
    for (int i = 0; i < count; i++) {
        if (strcmp(list[i].ssid, ssid) == 0) {
            return i;
        }
    }
    return -1;
}
//进行qsort前，此未降序操作
int cmp_signal_desc(const void *a, const void *b) {
    wifi_info_t *wa = (wifi_info_t *)a;
    wifi_info_t *wb = (wifi_info_t *)b;
    return wb->signal - wa->signal;
}
//显示以连接WiFi名称和周围已有的WiFi和过滤掉信号强度低于50的WiFi
void scan_wifi_json() { 
    
    get_current_wifi();
    char line[100];
    //显示WiFi名称与信号强度
    FILE *fp = popen("nmcli -t -f SSID,SIGNAL dev wifi list", "r");
    if (!fp) {
        my_zlog_error("{\"error\": \"无法执行扫描命令\"}");
        return;
    }

    wifi_info_t wifi_list[MAX_WIFI_LIST];
    int wifi_count = 0;

    while (fgets(line, sizeof(line), fp)) {
        char *ssid = strtok(line, ":");
        char *signal_str = strtok(NULL, "\n");
        if (!ssid || !signal_str) continue;
        if (strlen(ssid) == 0) continue;

        int signal = atoi(signal_str);
        int idx = find_ssid(wifi_list, wifi_count, ssid);//去重 + 只保留信号最强的
        if (idx == -1) {
            if (wifi_count < MAX_WIFI_LIST) {
                strncpy(wifi_list[wifi_count].ssid, ssid, SSID_MAX_LEN - 1);
                wifi_list[wifi_count].ssid[SSID_MAX_LEN - 1] = '\0';
                wifi_list[wifi_count].signal = signal;
                wifi_count++;
            }
        } else {
            if (signal > wifi_list[idx].signal) {
                wifi_list[idx].signal = signal;
            }
        }
    }
    pclose(fp);

    qsort(wifi_list, wifi_count, sizeof(wifi_info_t), cmp_signal_desc);//通过信号强度进行排序

    //将WiFi信息转化为json格式
    cJSON *root = cJSON_CreateObject();
    cJSON *body = cJSON_CreateObject();
    cJSON *head = cJSON_CreateObject();
    cJSON_AddStringToObject(body, "current_connected", g_current_ssid[0] ? g_current_ssid : "");

    cJSON *array = cJSON_CreateArray();
    for (int i = 0; i < wifi_count; i++) {
        if (wifi_list[i].signal < 50) continue;  // 过滤信号小于50的
        cJSON *item = cJSON_CreateObject();
        cJSON_AddStringToObject(item, "ssid", wifi_list[i].ssid);
        cJSON_AddNumberToObject(item, "strength", wifi_list[i].signal);
        cJSON_AddItemToArray(array, item);
    }

    cJSON_AddItemToObject(body, "available_wifi", array);
    cJSON_AddNumberToObject(head, "message_type", 3003);
    cJSON_AddItemToObject(root, "body", body);
    cJSON_AddItemToObject(root, "head",head);

    char *json_str = cJSON_Print(root);
    if (json_str) {
        my_zlog_debug("%s", json_str);

        mqtt_publish_to_all(mqtt_topic_pure_number(), json_str, 0);
        
        free(json_str);
    }
    cJSON_Delete(root);
}

//连接WiFi
int connect_wifi(const char* ssid, const char* password) {
    char cmd[CMD_BUFFER_SIZE];
    snprintf(cmd, sizeof(cmd), "nmcli dev wifi connect '%s' password '%s' 2>&1", ssid, password);

    my_zlog_info("🔌 正在连接 Wi-Fi：%s...", ssid);

    FILE *fp = popen(cmd, "r");
    if (!fp) {
        my_zlog_warn("❌ 无法执行连接命令。");
        return -1;
    }

    char output[512] = {0};
    size_t bytes_read =fread(output, 1, sizeof(output) - 1, fp);
    if (bytes_read == 0){
         my_zlog_debug("success");
    }
    pclose(fp);

    if (strstr(output, "successfully activated")) {
        my_zlog_debug("✅ 已成功连接到：%s", ssid);
        return 0;
    } else if (strstr(output, "No network with SSID")) {
        my_zlog_warn("❌ 连接失败：Wi-Fi '%s' 不存在。", ssid);
        return -2;
    } else if (strstr(output, "Secrets were required") || strstr(output, "incorrect password")) {
        my_zlog_warn("❌ 连接失败：密码错误。");
        return -3;
    } else {
        my_zlog_error("❌ 连接失败，未知错误：%s", output);
        return -4;
    }
}
//如果连接失败则回退
int connect_wifi_with_fallback(const char* ssid, const char* password, const char* fallback_ssid) {
    int ret = connect_wifi(ssid, password);
    if (ret != 0 && fallback_ssid && fallback_ssid[0] != 0) {
        my_zlog_warn("⚠️ 连接失败，尝试回退连接原Wi-Fi：%s", fallback_ssid);
        char cmd[CMD_BUFFER_SIZE];
        snprintf(cmd, sizeof(cmd), "nmcli dev wifi connect '%s' 2>&1", fallback_ssid);
        FILE *fp = popen(cmd, "r");
        if (fp) {
            char output[512] = {0};
            
            size_t bytes_read =fread(output, 1, sizeof(output) - 1, fp);
             if (bytes_read == 0){
                my_zlog_debug("fread success");
            }

            pclose(fp);
            if (strstr(output, "successfully activated")) {
                my_zlog_debug("✅ 回退连接成功：%s", fallback_ssid);
            } else {
                my_zlog_warn("❌ 回退连接失败：%s", output);
                ret = -5;
            }
        } else {
            my_zlog_error("❌ 无法执行回退连接命令。");
            ret = -5;
        }
    }
    return ret;
}
//改变WiFi连接
int change_wifi_connect(const char *wifi_ssid,const char *wifi_password) {
    get_current_wifi();
    int ret = connect_wifi_with_fallback(wifi_ssid, wifi_password, g_current_ssid);
    my_zlog_info("WiFi连接返回代码：%d", ret);
    return ret;
}

// 连续尝试 2 次 ping，任意一次成功即认为联网成功
int can_access_internet() { 
    for (int i = 0; i < 10; ++i) {
        int ret = system("ping -c 1 -W 1 baidu.com > /dev/null 2>&1");
        if (ret == 0) {
            return 0; // 有一次成功就返回 true
        }
    }
    return 1; // 都失败
}

//删除对应wifi
int delete_wifi_by_ssid(const char* ssid) {
    if (ssid == NULL || strlen(ssid) == 0) {
        fprintf(stderr, "SSID is empty.\n");
        return -1;
    }

    if (strcmp(ssid, default_SSID) == 0) {
        my_zlog_warn("默认WiFi %s 不允许删除", default_SSID);
        return -1;
    }

    char command[256];
    // 直接尝试删除这个名字的连接（假设连接名就是 SSID）
    snprintf(command, sizeof(command), "nmcli connection delete \"%s\"", ssid);

    int ret = system(command);
    if (ret == 0) {
        my_zlog_debug("Successfully deleted WiFi connection named: %s", ssid);
    } else {
        my_zlog_warn("Failed to delete WiFi connection named: %s", ssid);
    }

    return ret;
}


// 检查文件是否存在，不存在则创建
int check_or_create_wifi_conf() {
    struct stat st;
    if (stat(WIFI_CONF_PATH, &st) == 0) {
        // 文件已存在
        return 0;
    }

    // 创建空配置文件
    FILE *fp = fopen(WIFI_CONF_PATH, "w");
    if (!fp) {
        perror("Failed to create device_wifi.conf");
        return -1;
    }
    fclose(fp);
    return 0;
}

// 执行命令并获取结果,通过此函数获取到WiFi密码
char *get_command_output(const char *cmd, char *buffer, size_t size) {
    FILE *fp = popen(cmd, "r");
    if (!fp) return NULL;
    if (fgets(buffer, size, fp)) {
        buffer[strcspn(buffer, "\n")] = '\0'; // 去除换行符
    }
    pclose(fp);
    return buffer;
}
// 写入当前 WiFi SSID 和密码到配置文件
int write_wifi_conf() {
    char ssid[128] = {0};
    char cmd[256];
    char password[128] = {0};

    // 获取 SSID
    if (!get_command_output("iwgetid -r", ssid, sizeof(ssid))) {
        fprintf(stderr, "获取当前连接的 SSID 失败\n");
        return -1;
    }

    // 从 NetworkManager 配置中获取密码
    snprintf(cmd, sizeof(cmd),
             "grep -r '^psk=' /etc/NetworkManager/system-connections/ | grep '%s' | head -n1 | cut -d'=' -f2",
             ssid);
    if (!get_command_output(cmd, password, sizeof(password))) {
        fprintf(stderr, "获取 WiFi 密码失败（可能无权限或未使用 NetworkManager）\n");
        return -1;
    }

    // 写入文件
    FILE *fp = fopen(WIFI_CONF_PATH, "w");
    if (!fp) {
        my_zlog_error("打开配置文件失败");
        return -1;
    }

    fprintf(fp, "SSID=%s\n", ssid);
    fprintf(fp, "PASSWORD=%s\n", password);
    fclose(fp);

    my_zlog_debug("已写入到配置文件: %s\n", WIFI_CONF_PATH);
    return 0;
}

//删除对应的存在ssid的conf
void delete_wifi_conf() {
    DIR *dir = opendir(WIFI_CONF_DIR);
    if (!dir) {
        my_zlog_warn("opendir failed");
        return;
    }

    struct dirent *entry;
    char full_path[1024];

    while ((entry = readdir(dir)) != NULL) {
        // 只查找文件名为 "device_wifi.conf"
        if (strcmp(entry->d_name, "device_wifi.conf") == 0) {
            snprintf(full_path, sizeof(full_path), "%s/%s", WIFI_CONF_DIR, entry->d_name);
            if (unlink(full_path) == 0) {
                my_zlog_debug("Deleted: %s\n", full_path);
            } else {
                my_zlog_warn("Failed to delete");
            }
            break;  // 找到并删除就退出
        }
    }

    closedir(dir);
}

//提取WiFi名称和密码
int extract_wifi_file(){
    FILE *fp = fopen(WIFI_CONF_PATH, "r");
    if (fp == NULL) {
        perror("无法打开配置文件");
        return -1;
    }

    char line[256];

    while (fgets(line, sizeof(line), fp)) {
        // 去除换行符
        line[strcspn(line, "\r\n")] = 0;

        if (strncmp(line, "SSID=", 5) == 0) {
            strncpy(s_wifi_last_ssid, line + 5, sizeof(s_wifi_last_ssid) - 1);
        } else if (strncmp(line, "PASSWORD=", 9) == 0) {
            strncpy(s_wifi_last_password, line + 9, sizeof(s_wifi_last_password) - 1);
        }
    }

    fclose(fp);

    my_zlog_debug("SSID: %s", s_wifi_last_ssid);
    my_zlog_debug("PASSWORD: %s", s_wifi_last_password);

    return 0;
}

// 从文件读取 SSID，比较当前连接的 WiFi 名称
int compare_ssid_with_file() {
    char file_ssid[128] = {0};
    get_current_wifi();
    FILE *fp = fopen(WIFI_CONF_PATH, "r");
    if (!fp) {
        perror("Failed to open device_wifi.conf");
        return -1;
    }

    char line[256];
    while (fgets(line, sizeof(line), fp)) {
        if (strncmp(line, "SSID=", 5) == 0) {
            strncpy(file_ssid, line + 5, sizeof(file_ssid) - 1);
            file_ssid[strcspn(file_ssid, "\n")] = 0;
            break;
        }
    }
    fclose(fp);


    my_zlog_debug("File SSID: %s", file_ssid);
    my_zlog_debug("Current SSID: %s", g_current_ssid);

    if (strcmp(file_ssid, g_current_ssid) == 0) {
        my_zlog_debug("wifi没有发生改变或其他问题");
        return 0;
    } else {
        my_zlog_debug("wifi发生改变或其他问题");
        return 1;
    }
}

/*当wifi_status为0为连接jking,当wifi_status为1为修改成功，2是继续使用正常wifi，3是恢复到默认jking，4为wifi不存在
，5为密码错误，6为未知错误，7为回退失败，8为没网切回默认wifi*/
void wifichange_sendmqtt(int wifi_status) { //改WiFi发送

    get_current_wifi();
    cJSON *root = cJSON_CreateObject();
    cJSON *body = cJSON_CreateObject();
    cJSON *head = cJSON_CreateObject();

    cJSON_AddNumberToObject(body, "wifi_status", wifi_status);//为0成功
    cJSON_AddStringToObject(body, "wifi_ssid", g_current_ssid);//为0成功

    cJSON_AddNumberToObject(head, "message_type",3004);

    cJSON_AddItemToObject(root, "body", body);
    cJSON_AddItemToObject(root, "head",head);

    char *payload = cJSON_PrintUnformatted(root);
    my_zlog_debug("%s",payload);
    
    mqtt_publish_to_all(mqtt_topic_pure_number(), payload, 0);
    
    free(payload);
    cJSON_Delete(root);
}

//默认连接jking
void connect_wifi_jking() {
    if(check_or_create_wifi_conf() == 0) my_zlog_debug("文件已创建");
    if(write_wifi_conf() == 0) my_zlog_debug("写入成功");
    int ret=change_wifi_connect(default_SSID,default_password);
    delay_s(15); 
    if(can_access_internet()==0) {
        if(system("sudo reboot")!=0){//重启香橙派
            my_zlog_error("reboot fail");
        }
        my_zlog_info("重启成功");
    }
}

//wifi改变初始化，放在main开头,必须要等mqtt直播就绪才行
int wifi_change_sendmqtt_init(){
    int wififile_fd = compare_ssid_with_file();
    if(wififile_fd==-1){
        if(can_access_internet()!=0){
            get_current_wifi();
            if(strcmp(default_SSID,g_current_ssid)==0){
                my_zlog_debug("没有更改WiFi");
                return 0;
            }
            check_or_create_wifi_conf();
            write_wifi_conf();
            change_wifi_connect(default_SSID,default_password);
            delete_wifi_by_ssid(g_current_ssid);
        }
        if(strcmp(default_SSID,g_current_ssid)==0)  wifichange_sendmqtt(0); 

    }else if(wififile_fd==1){
        get_current_wifi();
        if(strcmp(default_SSID,g_current_ssid)==0){
            extract_wifi_file();
            if(change_wifi_connect(s_wifi_last_ssid,s_wifi_last_password)==0){
                delay_s(15); 
                if(can_access_internet()==0){
                delete_wifi_by_ssid(g_current_ssid);
                delete_wifi_conf();
                my_zlog_debug("成功回朔到上次WiFi");
                }else {
                    change_wifi_connect(default_SSID,default_password);
                    my_zlog_debug("成功回朔到上次WiFi但没网回到默认wifi");
                }

            }else {
                change_wifi_connect(default_SSID,default_password);
                my_zlog_debug("说明不止一次更换wifi过");
            }
        }else{
            if(can_access_internet()==0){
                wifichange_sendmqtt(1);
                my_zlog_debug("wifi更改成功");
                delete_wifi_conf();
            }else {
                if(change_wifi_connect(default_SSID,default_password)==0)delete_wifi_conf();
                my_zlog_debug("WiFi无网切回");
                delay_s(10);
            }

        }
        
    } else if(wififile_fd==0){
       if(can_access_internet()==0) {
            wifichange_sendmqtt(2);//2是继续使用正常wifi
             my_zlog_debug("wifi更改失败，继续使用原WiFi，可使用查询指令查询");
            delete_wifi_conf();
       } else {//不需要删除文件，不同回删除conf源文件，相同也会删除
            wifichange_sendmqtt(3);//3是恢复到默认jking
            my_zlog_debug("在WiFi更改失败情况下使用默认连接jking");
            delete_wifi_conf();
            connect_wifi_jking();
       }
    }
    return 0;
}

//接收mqtt消息
void wifi_change_recmqtt(cJSON *body){
    cJSON *wifi_ssid = cJSON_GetObjectItem(body, "wifi_ssid");
    cJSON *wifi_password = cJSON_GetObjectItem(body, "wifi_password");
    cJSON *wifi_status = cJSON_GetObjectItem(body, "wifi_status");
    if(cJSON_IsString(wifi_ssid)  && cJSON_IsString(wifi_password)){
        char *ssid = wifi_ssid->valuestring,*password=wifi_password->valuestring;
        int wifi_statustemp = wifi_status->valueint;
        if(check_or_create_wifi_conf() == 0) my_zlog_debug("文件已创建");
        if(write_wifi_conf() == 0) my_zlog_debug("写入成功");
        int ret = change_wifi_connect(ssid,password);
        delay_s(15);  
        if(strcmp(default_SSID,ssid)==0){
            delete_wifi_by_ssid(g_current_ssid);
            my_zlog_debug("ssid:%S",g_current_ssid);
            delete_wifi_conf();
            if(system("sudo reboot")!=0){//重启香橙派
                my_zlog_error("reboot fail");
            }
            my_zlog_info("重启成功");
        } 
        if(ret == 0){
            if(can_access_internet()==0){
                delete_wifi_by_ssid(g_current_ssid);
                my_zlog_debug("ssid:%S",g_current_ssid);
                if(system("sudo reboot")!=0){//重启香橙派
                    my_zlog_error("reboot fail");
                my_zlog_info("重启成功");
            }else {
                delete_wifi_conf();
                if(change_wifi_connect(default_SSID,default_password)==0) delete_wifi_by_ssid(g_current_ssid);
                 my_zlog_debug("无网切回默认WiFi");
                 delay_s(15); 
                wifichange_sendmqtt(8);
            }
        }
        if(ret == -1) {
            wifichange_sendmqtt(4);
        }else if(ret == -2){
            wifichange_sendmqtt(5);
        }else if(ret == -3){
            wifichange_sendmqtt(6);
        }else if(ret == -4 || ret == -5){
            wifichange_sendmqtt(7);
            if(system("sudo reboot")!=0){//重启香橙派
                my_zlog_error("reboot fail");
            }
            my_zlog_info("重启成功");
        }
    }

    }
}