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

#define MAX_WIFI_ENTRIES 11
#define MAX_SAVED_WIFI_SLOTS 10
#define SSID_MAX_LENGTH 64
#define NM_CONN_DIR "/etc/NetworkManager/system-connections/"

typedef struct {
    char ssid[SSID_MAX_LENGTH];
    time_t mtime;
} saved_wifi_entry_t;

static int is_default_wifi_ssid(const char *ssid) {
    return ssid != NULL && strcmp(ssid, default_SSID) == 0;
}

static int connection_name_from_filename(const char *filename, char *ssid_out, size_t ssid_size) {
    const char *dot = strrchr(filename, '.');
    if (dot && strcmp(dot, ".nmconnection") == 0) {
        size_t name_len = (size_t)(dot - filename);
        if (name_len == 0 || name_len >= ssid_size) {
            return -1;
        }
        strncpy(ssid_out, filename, name_len);
        ssid_out[name_len] = '\0';
        return 0;
    }

    if (strlen(filename) >= ssid_size) {
        return -1;
    }
    strncpy(ssid_out, filename, ssid_size - 1);
    ssid_out[ssid_size - 1] = '\0';
    return 0;
}

static int is_wifi_nmconnection_file(const char *filepath) {
    FILE *fp = fopen(filepath, "r");
    if (!fp) {
        return 0;
    }

    char line[256];
    int is_wifi = 0;
    while (fgets(line, sizeof(line), fp)) {
        if (strncmp(line, "type=wifi", 9) == 0 ||
            strncmp(line, "type=802-11-wireless", 20) == 0) {
            is_wifi = 1;
            break;
        }
    }

    fclose(fp);
    return is_wifi;
}

static int wifi_connection_exists(const char *ssid) {
    char path[512];
    snprintf(path, sizeof(path), "%s%s.nmconnection", NM_CONN_DIR, ssid);
    return access(path, F_OK) == 0;
}

static int collect_saved_wifi_entries(saved_wifi_entry_t *entries, int max_count) {
    DIR *dir = opendir(NM_CONN_DIR);
    if (!dir) {
        my_zlog_error("无法打开NetworkManager配置目录");
        return -1;
    }

    struct dirent *entry;
    int count = 0;

    while ((entry = readdir(dir)) != NULL && count < max_count) {
        if (entry->d_type != DT_REG && entry->d_type != DT_UNKNOWN) {
            continue;
        }

        char ssid[SSID_MAX_LENGTH];
        if (connection_name_from_filename(entry->d_name, ssid, sizeof(ssid)) != 0) {
            continue;
        }

        char filepath[512];
        snprintf(filepath, sizeof(filepath), "%s%s", NM_CONN_DIR, entry->d_name);
        if (!is_wifi_nmconnection_file(filepath)) {
            continue;
        }

        struct stat st;
        if (stat(filepath, &st) != 0) {
            continue;
        }

        strncpy(entries[count].ssid, ssid, sizeof(entries[count].ssid) - 1);
        entries[count].ssid[sizeof(entries[count].ssid) - 1] = '\0';
        entries[count].mtime = st.st_mtime;
        count++;
    }

    closedir(dir);
    return count;
}

static int count_non_default_saved_wifi(void) {
    saved_wifi_entry_t entries[MAX_WIFI_ENTRIES];
    int count = collect_saved_wifi_entries(entries, MAX_WIFI_ENTRIES);
    if (count < 0) {
        return -1;
    }

    int non_default_count = 0;
    for (int i = 0; i < count; i++) {
        if (!is_default_wifi_ssid(entries[i].ssid)) {
            non_default_count++;
        }
    }
    return non_default_count;
}

static int find_oldest_non_default_wifi(char *ssid_out, size_t ssid_size) {
    saved_wifi_entry_t entries[MAX_WIFI_ENTRIES];
    int count = collect_saved_wifi_entries(entries, MAX_WIFI_ENTRIES);
    if (count <= 0) {
        return -1;
    }

    int found = 0;
    time_t oldest_mtime = 0;

    for (int i = 0; i < count; i++) {
        if (is_default_wifi_ssid(entries[i].ssid)) {
            continue;
        }
        if (!found || entries[i].mtime < oldest_mtime) {
            oldest_mtime = entries[i].mtime;
            strncpy(ssid_out, entries[i].ssid, ssid_size - 1);
            ssid_out[ssid_size - 1] = '\0';
            found = 1;
        }
    }

    return found ? 0 : -1;
}

static int enforce_saved_wifi_limit(const char *new_ssid) {
    if (is_default_wifi_ssid(new_ssid) || wifi_connection_exists(new_ssid)) {
        return 0;
    }

    int count = count_non_default_saved_wifi();
    if (count < 0) {
        return -1;
    }

    while (count >= MAX_SAVED_WIFI_SLOTS) {
        char oldest_ssid[SSID_MAX_LENGTH];
        if (find_oldest_non_default_wifi(oldest_ssid, sizeof(oldest_ssid)) != 0) {
            my_zlog_error("非默认WiFi已达上限，但未找到可删除的最旧配置");
            return -1;
        }

        if (delete_wifi_by_ssid(oldest_ssid) != 0) {
            my_zlog_error("删除最旧WiFi失败: %s", oldest_ssid);
            return -1;
        }

        my_zlog_info("非默认WiFi已达%d个上限，删除最旧配置: %s", MAX_SAVED_WIFI_SLOTS, oldest_ssid);
        count--;
    }

    return 0;
}

static int update_wifi_password(const char *ssid, const char *password) {
    char cmd[256];
    snprintf(cmd, sizeof(cmd),
        "nmcli connection modify \"%s\" wifi-sec.key-mgmt wpa-psk wifi-sec.psk \"%s\"",
        ssid, password);

    if (system(cmd) != 0) {
        my_zlog_error("更新WiFi密码失败: %s", ssid);
        return -1;
    }

    my_zlog_info("已更新WiFi密码: %s", ssid);
    return 0;
}

/*成功发送3010：0保存成功，1删除成功，2保存失败，3默认WiFi不可删，4删除失败*/
void device_wifi_public_sendmqtt(int wifi_status) {
    get_current_wifi();
    cJSON *root = cJSON_CreateObject();
    cJSON *body = cJSON_CreateObject();
    cJSON *head = cJSON_CreateObject();

    cJSON_AddNumberToObject(body, "wifi_status", wifi_status);
    cJSON_AddNumberToObject(head, "message_type", 3010);

    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);
}

void device_wifi_rec_delete(cJSON *body) {
    cJSON *wifi_ssid = cJSON_GetObjectItem(body, "wifi_ssid");
    if (!cJSON_IsString(wifi_ssid)) {
        return;
    }

    char *ssid = wifi_ssid->valuestring;
    if (is_default_wifi_ssid(ssid)) {
        my_zlog_warn("默认WiFi %s 不允许删除", default_SSID);
        device_wifi_public_sendmqtt(3);
        return;
    }

    if (delete_wifi_by_ssid(ssid) == 0) {
        my_zlog_info("删除成功");
        device_wifi_public_sendmqtt(1);
    } else {
        my_zlog_info("删除失败");
        device_wifi_public_sendmqtt(4);
    }
}

int orange_pi_save_wifi(const char *ssid, const char *password) {
    if (!ssid || !password || strlen(ssid) == 0 || strlen(password) == 0) {
        fprintf(stderr, "[ERROR] SSID或密码为空\n");
        return -1;
    }

    if (strpbrk(ssid, "\"`$|") || strpbrk(password, "\"`$|")) {
        fprintf(stderr, "[ERROR] 检测到非法字符\n");
        return -1;
    }

    if (wifi_connection_exists(ssid)) {
        return update_wifi_password(ssid, password);
    }

    if (enforce_saved_wifi_limit(ssid) != 0) {
        return -1;
    }

    char cmd[512];
    snprintf(cmd, sizeof(cmd),
        "nmcli connection add type wifi con-name \"%s\" ifname wlan0 ssid \"%s\" wifi-sec.key-mgmt wpa-psk wifi-sec.psk \"%s\"",
        ssid, ssid, password);

    if (system(cmd) != 0) {
        my_zlog_error("[ERROR] 保存配置失败: %s", ssid);
        return -1;
    }

    my_zlog_info("[SUCCESS] 已保存WiFi配置: %s", ssid);
    return 0;
}

void device_wifi_rec_sava(cJSON *body) {
    cJSON *wifi_ssid = cJSON_GetObjectItem(body, "wifi_ssid");
    cJSON *wifi_password = cJSON_GetObjectItem(body, "wifi_password");
    if (cJSON_IsString(wifi_ssid) && cJSON_IsString(wifi_password)) {
        char *ssid = wifi_ssid->valuestring;
        char *password = wifi_password->valuestring;
        my_zlog_debug("接收到保存WiFi名称和密码");
        if (orange_pi_save_wifi(ssid, password) == 0) {
            device_wifi_public_sendmqtt(0);
        } else {
            device_wifi_public_sendmqtt(2);
        }
    }
}

int get_saved_wifi_list(char ssid_list[][SSID_MAX_LENGTH], int max_count) {
    saved_wifi_entry_t entries[MAX_WIFI_ENTRIES];
    int limit = max_count < MAX_WIFI_ENTRIES ? max_count : MAX_WIFI_ENTRIES;
    int count = collect_saved_wifi_entries(entries, limit);
    if (count < 0) {
        return -1;
    }

    for (int i = 0; i < count; i++) {
        strncpy(ssid_list[i], entries[i].ssid, SSID_MAX_LENGTH - 1);
        ssid_list[i][SSID_MAX_LENGTH - 1] = '\0';
    }

    return count;
}

void device_send_saved_wifi() {
    get_current_wifi();

    char list_wifi[MAX_WIFI_ENTRIES][SSID_MAX_LENGTH];
    int count = get_saved_wifi_list(list_wifi, MAX_WIFI_ENTRIES);
    if (count < 0) {
        my_zlog_error("读取已保存WiFi配置失败");
        return;
    }

    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 < count; i++) {
        cJSON *item = cJSON_CreateObject();
        my_zlog_debug("%d. %s\n", i + 1, list_wifi[i]);
        cJSON_AddStringToObject(item, "ssid", list_wifi[i]);
        cJSON_AddItemToArray(array, item);
    }
    cJSON_AddItemToObject(body, "available_wifi", array);
    cJSON_AddNumberToObject(head, "message_type", 3012);
    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);
}
