////////////////////////////////////////////////////////////////////////////////////////////////////
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <list>
#include <map>
#include <thread>
#include <mutex>
#include <atomic>
#include <cstdio>
#include <sstream>
#include <algorithm>
#include <cctype>
#include <fnmatch.h>
#include <chrono>
#include <cstring>
#include <cstdlib>
#include <ctime>

// socket 网络编程
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/select.h>      
#include <sys/stat.h>   

////////////////////////////////////////////////////////////////////////////////////////////////////

#include "worker.h"
#include "interface.h"
#include "rocketmq.h"
#include "log4.h"
#include "front.h"

/////////////////////////////////////////////////////////////////////////////////////////////////////

//shell日志打印开关
bool showinshellflag =false;

////////////////////////////////////////////////////////////////////////////////////////////////////

extern std::list<std::string> errorList, warnList, normalList;
extern std::mutex errorListMutex, warnListMutex, normalListMutex;

extern int IED_COUNT;
extern std::atomic<int> INITFLAG;
extern int g_front_seg_index;
extern std::string subdir;

extern int G_TEST_NUM;
extern int G_TEST_TYPE;
extern int LEDGER_MAX_ITEMS;

extern bool errorOutputEnabled;
extern bool warnOutputEnabled;
extern bool normalOutputEnabled;

////////////////////////////////////////////////////////////////////////////////////////////////////测试登录类

    Worker::Worker(Front* front) 
        : m_front(front), listenFD(-1), running(false), historyIndex(-1), stopViewLog(true), g_stopTelnetTest(true) {}

    Worker::~Worker() {
        stopServer();
    }

    // 启动 Telnet 服务（监听端口）
    bool Worker::startServer(int port) {
        if (running) return false;

        listenFD = socket(AF_INET, SOCK_STREAM, 0);
        if (listenFD < 0) return false;

        int opt = 1;
        setsockopt(listenFD, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

        sockaddr_in addr{};
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_port = htons(port);

        if (bind(listenFD, (sockaddr*)&addr, sizeof(addr)) < 0) return false;
        if (listen(listenFD, 5) < 0) return false;

        running = true;
        serverThread = std::thread(&Worker::acceptLoop, this);

        std::thread periodicThread(&Worker::doPeriodicTask, this);
        periodicThread.detach();

        return true;
    }

    // 停止 Telnet 服务
    void Worker::stopServer() {
        if (!running) return;
        running = false;
        shutdown(listenFD, SHUT_RDWR);
        close(listenFD);
        if (serverThread.joinable()) serverThread.join();
    }

    // 发送字符串
    void Worker::sendStr(int fd, const std::string& s) {
        send(fd, s.c_str(), s.size(), 0);
    }

    // 接收客户端连接主循环
    void Worker::acceptLoop() {
        while (running) {
            sockaddr_in caddr;
            socklen_t clen = sizeof(caddr);
            int cfd = accept(listenFD, (sockaddr*)&caddr, &clen);
            if (cfd >= 0) std::thread(&Worker::sessionThread, this, cfd).detach();
        }
    }

    //打印提示符
    void Worker::printPrompt(int clientFD)
    {
        sendStr(clientFD, "\r\n>");
    }

    // 客户端会话线程处理函数
    void Worker::sessionThread(int clientFD) {
        sendTelnetNegotiation(clientFD);
        sendStr(clientFD, "\r\nWelcome to the test shell. Type 'help'.\r\n> ");

        while (true) {
            char buf[512];
            int n = recv(clientFD, buf, sizeof(buf), 0);
            if (n <= 0) break;

            for (int i = 0; i < n; ++i) {
                unsigned char c = (unsigned char)buf[i];

                // 如果不是可打印字符，且也不是 上/下箭头、退格、回车等，就忽略
                bool isPrintable = (c >= 32 && c <= 126);   //可见字符范围
                bool isArrowOrEsc = (c == 0x1b);            //ESC
                bool isEnter = (c == '\r' || c == '\n');    //换行
                bool isBackspace = (c == 0x7f || c == 0x08);//退格
                bool isTab = (c == '\t');                   //tab
                if( !isPrintable && !isArrowOrEsc && !isEnter && !isBackspace && !isTab )
                {
                    // 跳过不认识的控制字符：如 '\0'
                    continue;
                }

                // Telnet 协议协商处理
                if (c == IAC) {
                    if (i + 1 < n && (buf[i+1] == TELDO || buf[i+1] == DONT || buf[i+1] == WILL || buf[i+1] == WONT)) i += 2;
                    else i++;
                    continue;
                }

                // 退出 viewlog / telnet 流程
                if (c == '`') {
                    stopViewLog = true;        // [MOD] 支持停止日志查看
                    g_stopTelnetTest = true;   // [MOD] 停止 telnet 测试
                    sendStr(clientFD, "\r\n[Log view stopped]\r\n> ");
                    continue;
                }

                // 2) 回车/换行 => 执行命令
                if (c == '\r' || c == '\n')
                {
                    // 如果当前是 '\r' 并且下一个是 '\n'，就跳过 '\n'
                    if (c == '\r') {
                        if (i + 1 < n && buf[i+1] == '\n') {
                            i++;
                        }
                        // 这里再加一步，如果紧跟着是 '\0'，也跳过
                        if (i + 1 < n && buf[i+1] == '\0') {
                            i++;
                        }
                    }
                    // 如果当前是 '\n'，也可以检查一下下一个是不是 '\0'（有些客户端可能发 '\n\0'）
                    else {
                        if (i + 1 < n && buf[i+1] == '\0') {
                            i++;
                        }
                    }
                
                    // 现在把 当前输入的指令 前后空白去掉
                    std::string cmdtrim = trim(currentCommand);
                    if (!cmdtrim.empty()) {     //输入指令非空则记录到历史
                        
                        if (commandHistory.empty() || commandHistory.back() != cmdtrim) {   //防止连续重复的历史记录
                            commandHistory.push_back(cmdtrim);
                        }

                        historyIndex = commandHistory.size();   //更新历史指令下标
                
                        processCommand(cmdtrim, clientFD);      //处理当前指令
                    }
                
                    // 处理后清空并打印新的提示符
                    currentCommand.clear();
                    printPrompt(clientFD);
                
                    // 回车后处理新的命令行
                    continue;
                }

                // 上/下箭头处理
                if (c == 0x1b && i + 2 < n && buf[i+1] == '[') {
                    char arrow = buf[i+2];
                    if (arrow == 'A') handleUpArrow(clientFD);
                    else if (arrow == 'B') handleDownArrow(clientFD);
                    i += 2;
                    continue;
                }

                // 退格处理
                if (c == 0x7f || c == 0x08) {
                    if (!currentCommand.empty()) {
                        currentCommand.pop_back();
                        sendStr(clientFD, "\b \b");
                    }
                    continue;
                }

                // 普通字符输入
                currentCommand.push_back((char)c);
                sendBytes(clientFD, (const char*)&c, 1);
            }
        }

        close(clientFD);
    }

    // 发送 Telnet 协商指令
    void Worker::sendTelnetNegotiation(int clientFD) {
        unsigned char will_echo[3] = { IAC, WILL, TELOPT_ECHO };
        unsigned char will_sga[3] = { IAC, WILL, TELOPT_SUPPRESS_GO_AHEAD };
        unsigned char dont_lin[3] = { IAC, DONT, TELOPT_LINEMODE };
        sendBytes(clientFD, (const char*)will_echo, 3);
        sendBytes(clientFD, (const char*)will_sga, 3);
        sendBytes(clientFD, (const char*)dont_lin, 3);
    }

    // 发送字节数组
    void Worker::sendBytes(int fd, const char* buf, int len) {
        send(fd, buf, len, 0);
    }

    void Worker::setTestNum(int num) {
        std::lock_guard<std::mutex> locker(testMutex);
        G_TEST_NUM = num;
    }

    void Worker::setTestType(int type) {
        std::lock_guard<std::mutex> locker(testMutex);
        G_TEST_TYPE = type;
    }

    void Worker::setMaxItems(int items) {
        std::lock_guard<std::mutex> locker(testMutex);
        LEDGER_MAX_ITEMS = items;
    }

    // 日志控制
    void Worker::setTestlog(bool flag) {
        redirectErrorOutput(flag);
        redirectWarnOutput(flag);
        redirectNormalOutput(flag);
    }

    void Worker::doPeriodicTask() {
        while (running) {
            {
                std::lock_guard<std::mutex> locker(testMutex);
                std::cout << "[PeriodicTask] G_TEST_NUM = " << G_TEST_NUM 
                          << ", G_TEST_TYPE = " << G_TEST_TYPE << std::endl;

                if (G_TEST_NUM != 0) {
                    std::cout << "[PeriodicTask] Executing rocketmq_test_300()\n";
                    rocketmq_test_300(G_TEST_NUM, g_front_seg_index, G_TEST_TYPE,m_front);
                    //upload_data_test();
                }
            }

            std::this_thread::sleep_for(std::chrono::seconds(60)); // 每 60 秒执行一次
        }
    }

    // 命令处理逻辑扩展
    void Worker::processCommand(const std::string &cmd, int clientFD) {
        std::cout << "Received command: " << cmd << std::endl;

        if (cmd == "help") {
            std::string helpText =
                "Available commands:\r\n"
                "G_TEST_NUM=<num>   - Set the G_TEST_NUM\r\n"
                "G_TEST_TYPE=<num>   - Set the G_TEST_TYPE 0:use ledger,1:use number\r\n"
                "TESTLEDGER <processNo>,<start>,<count> - Batch send UD ledger updates (e.g. TESTLEDGER 3,1,50)\r\n"
                "LOG=<bool>       - Set the LOG\r\n"
                "LOGLIST          - List all registered loggers\r\n"
                "MAX=<int>        - Set the MAX_ITEMS\r\n"
                "dir               - Execute rocketmq_test_getdir\r\n"
                "rc               - Execute rocketmq_test_rc\r\n"
                "rt               - Execute rocketmq_test_rt\r\n"
                "ud               - Execute rocketmq_test_ud\r\n"
                "set              - Execute rocketmq_test_set\r\n"
                "log              - Execute rocketmq_test_log\r\n"
                "upload           - Execute upload file\r\n"
                "qvvr             - Execute http_test_qvvr\r\n"
                "ledger <id>      - Execute ledger with optional terminal_id\r\n"
                "viewlog <level>  - View logs (ERROR, WARN, NORMAL, DEBUG)\r\n"
                "value <valuename> - Execute value print with valuename\r\n"
                "exit             - Exit the shell\r\n"
                "help             - Show this help message\r\n";
            sendStr(clientFD, "\r\x1B[K" + helpText);
        } else if (cmd.find("TESTLEDGER") == 0) {
            // 支持：TESTLEDGER 3,1,50（中间允许空格）
            size_t pos = cmd.find(' ');
            if (pos == std::string::npos || pos + 1 >= cmd.size()) {
                sendStr(clientFD, "\r\x1B[KUsage: TESTLEDGER <processNo>,<start>,<count>\r\n");
            } else {
                std::string args = cmd.substr(pos + 1);

                // 去掉可能的空格
                for (size_t i = 0; i < args.size(); ) {
                    if (args[i] == ' ' || args[i] == '\t' || args[i] == '\r' || args[i] == '\n')
                        args.erase(i, 1);
                    else
                        ++i;
                }

                // 解析三个整数
                int processNo = 0, start = 0, count = 0;
                size_t c1 = args.find(',');
                size_t c2 = (c1 == std::string::npos) ? std::string::npos : args.find(',', c1 + 1);

                if (c1 == std::string::npos || c2 == std::string::npos) {
                    sendStr(clientFD, "\r\x1B[KUsage: TESTLEDGER <processNo>,<start>,<count> (e.g. TESTLEDGER 3,1,50)\r\n");
                } else {
                    processNo = std::atoi(args.substr(0, c1).c_str());
                    start     = std::atoi(args.substr(c1 + 1, c2 - (c1 + 1)).c_str());
                    count     = std::atoi(args.substr(c2 + 1).c_str());

                    if (processNo <= 0 || start <= 0 || count <= 0) {
                        sendStr(clientFD, "\r\x1B[KInvalid args. Need >0. Example: TESTLEDGER 3,1,50\r\n");
                    } else {
                        // 调用批量发送（每条间隔1秒的逻辑在函数内部）
                        rocketmq_test_ud_batch(m_front, processNo, start, count);
                        sendStr(clientFD, "\r\x1B[KExecuted TESTLEDGER batch send\r\n");
                    }
                }
            }
        } else if (cmd.find("viewlog") == 0) {
            showinshellflag = true;
            handleViewLogCommand(cmd, clientFD);
        } else if (cmd.find("G_TEST_NUM=") == 0) {
            int num = std::atoi(cmd.substr(11).c_str());
            setTestNum(num);
            sendStr(clientFD, "\r\x1B[KTEST_NUM updated\r\n");
        } else if (cmd.find("G_TEST_TYPE=") == 0) {
            int type = std::atoi(cmd.substr(12).c_str());
            setTestType(type);
            sendStr(clientFD, "\r\x1B[KTEST_TYPE updated\r\n");
        } else if (cmd.find("LOG=") == 0) {
            int flag = std::atoi(cmd.substr(4).c_str());
            setTestlog(flag);
            sendStr(clientFD, "\r\x1B[KLOG updated\r\n");
        }else if (cmd == "LOGLIST" || cmd == "loglist") {
            std::ostringstream oss;
                
            // 1️⃣ 打印 logger_map
            oss << "\r\x1B[KRegistered loggers (" << logger_map.size() << "):\r\n";
            for (const auto& it : logger_map) {
                oss << "  " << it.first << "\r\n";
            }
        
            // 2️⃣ 打印 LogLevelCache（原子只读）
            std::shared_ptr<LogLevelCache> cache =
                std::atomic_load_explicit(&g_level_cache_sp, std::memory_order_acquire);
        
            if (!cache) {
                oss << "\r\x1B[K[LogLevelCache] <EMPTY>\r\n";
            } else {
                oss << "\r\x1B[K[LogLevelCache] terminal levels (" 
                    << cache->term_min.size() << "):\r\n";
            
                for (const auto& kv : cache->term_min) {
                    oss << "  terminal." << kv.first
                        << " -> " << loglevel_to_str(kv.second) << "\r\n";
                }
            
                oss << "\r\x1B[K[LogLevelCache] monitor levels (" 
                    << cache->mp_min.size() << "):\r\n";
            
                for (const auto& kv : cache->mp_min) {
                    oss << "  monitor." << kv.first
                        << " -> " << loglevel_to_str(kv.second) << "\r\n";
                }
            }
        
            sendStr(clientFD, oss.str());
        }else if (cmd.find("MAX=") == 0) {
            int flag = std::atoi(cmd.substr(4).c_str());
            setMaxItems(flag);
            sendStr(clientFD, "\r\x1B[KMAX_ITEMS updated\r\n");
        } 
        else if (cmd == "rc") {
            rocketmq_test_rc(m_front);
            sendStr(clientFD, "\r\x1B[KExecuted rocketmq_test_rc\r\n");
        } else if (cmd == "getdir") {
            rocketmq_test_getdir(m_front);
            sendStr(clientFD, "\r\x1B[KExecuted rocketmq_test_getdir\r\n");
        } else if (cmd == "rt") {
            rocketmq_test_rt(m_front);
            sendStr(clientFD, "\r\x1B[KExecuted rocketmq_test_rt\r\n");
        } else if (cmd == "ud") {
            rocketmq_test_ud(m_front);
            sendStr(clientFD, "\r\x1B[KExecuted rocketmq_test_ud\r\n");
        } else if (cmd == "set") {
            rocketmq_test_set(m_front);
            sendStr(clientFD, "\r\x1B[KExecuted rocketmq_test_set\r\n");
        } else if (cmd == "upload") {
            Fileupload_test();
            sendStr(clientFD, "\r\x1B[KExecuted upload file\r\n");
        } else if (cmd == "qvvr") {
            qvvr_test();
            sendStr(clientFD, "\r\x1B[KExecuted http_test_qvvr\r\n");
        } else if (cmd.find("ledger") == 0) {
            size_t pos = cmd.find(' ');
            if (pos != std::string::npos) {
                std::string terminalId = cmd.substr(pos + 1);
                ledger(terminalId.c_str(), clientFD);
                sendStr(clientFD, "\r\x1B[KExecuted ledger with terminal_id\r\n");
            } else {
                ledger("", clientFD);
                sendStr(clientFD, "\r\x1B[KExecuted ledger without parameters\r\n");
            }
        } else if (cmd.find("value") == 0) {
            size_t pos = cmd.find(' ');
            if (pos != std::string::npos) {
                std::string var = cmd.substr(pos + 1);
                sendStr(clientFD, "\r\x1B[KExecuted value with variable name: " + var + "\r\n");
                value_print(var, clientFD);
            } else {
                sendStr(clientFD, "\r\x1B[KPlease provide a variable name\r\n");
            }
        } else if (cmd == "exit") {
            sendStr(clientFD, "\r\x1B[KGoodbye! Exiting shell...\r\n");
            shutdown(clientFD, SHUT_RDWR);
            close(clientFD);
            return;
        } else {
            sendStr(clientFD, "\r\x1B[KUnknown command\r\n");
        }

        // 打印提示符
        sendStr(clientFD, "> ");
    }

    // 上箭头历史回溯
    void Worker::handleUpArrow(int fd) {
        if (!commandHistory.empty() && historyIndex > 0) {
            historyIndex--;
            currentCommand = commandHistory[historyIndex];
            sendStr(fd, "\r\x1B[K> " + currentCommand);
        }
    }

    // 下箭头历史前进
    void Worker::handleDownArrow(int fd) {
        if (!commandHistory.empty() && historyIndex < (int)commandHistory.size() - 1) {
            historyIndex++;
            currentCommand = commandHistory[historyIndex];
            sendStr(fd, "\r\x1B[K> " + currentCommand);
        } else {
            currentCommand.clear();
            sendStr(fd, "\r\x1B[K> ");
        }
    }

    // 字符串 trim
    std::string Worker::trim(const std::string& s) {
        auto start = s.begin();
        while (start != s.end() && std::isspace(*start)) ++start;
        auto end = s.end();
        do { --end; } while (std::distance(start, end) > 0 && std::isspace(*end));
        return (start <= end) ? std::string(start, end + 1) : "";
    }

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////测试shell用的函数

void Worker::printLedgerinshell(const terminal_dev& dev, int fd) {
    // —— 显示控制：最多打印的元素数量（防止过长）——
    const size_t MAX_ITEMS = static_cast<size_t>(LEDGER_MAX_ITEMS);  // 非 constexpr

    std::ostringstream os;
    os << "\r\x1B[K------------------------------------\n";

    os << "\r\x1B[K|-- guid             : " << dev.guid          << "\n";
    os << "\r\x1B[K|-- busytype         : " << dev.busytype      << "\n";
    os << "\r\x1B[K|-- isbusy           : " << dev.isbusy        << "\n";
    os << "\r\x1B[K|-- busytimecount    : " << dev.busytimecount << "\n";

    //os << "\r\x1B[K|-- dev_index        : " << dev.dev_index   << "\n";
    os << "\r\x1B[K|-- terminal_id      : " << dev.terminal_id   << "\n";
    os << "\r\x1B[K|-- terminal_name    : " << dev.terminal_name << "\n";
    os << "\r\x1B[K|-- dev_ip           : " << dev.addr_str      << "\n";
    os << "\r\x1B[K|-- dev_port         : " << dev.port          << "\n";
    os << "\r\x1B[K|-- dev_type         : " << dev.dev_type      << "\n";
    os << "\r\x1B[K|-- dev_key          : " << dev.dev_key       << "\n";
    os << "\r\x1B[K|-- dev_series       : " << dev.dev_series    << "\n";
    os << "\r\x1B[K|-- dev_processNo    : " << dev.processNo     << "\n";
    os << "\r\x1B[K|-- maxProcessNum    : " << dev.maxProcessNum << "\n";
    os << "\r\x1B[K|-- org_name         : " << dev.org_name      << "\n";
    os << "\r\x1B[K|-- maint_name       : " << dev.maint_name    << "\n";
    os << "\r\x1B[K|-- station_name     : " << dev.station_name  << "\n";
    os << "\r\x1B[K|-- tmnl_factory     : " << dev.tmnl_factory  << "\n";
    os << "\r\x1B[K|-- tmnl_status      : " << dev.tmnl_status   << "\n";
    os << "\r\x1B[K|-- timestamp        : " << dev.timestamp     << "\n";
    os << "\r\x1B[K|-- Righttime        : " << dev.Righttime     << "\n";
    os << "\r\x1B[K|-- mac              : " << dev.mac           << "\n";
    os << "\r\x1B[K|-- loglevel         : " << dev.DevLogLevel   << "\n";

    // ========================= 终端级 · 内部定值 =========================
    // internal_values（ushort 列表）与 dz_internal_info_list 一一对应，仅展示前 MAX_ITEMS 条
    os << "\r\x1B[K|-- Internal Values (" << dev.internal_values.size() << "):\n";
    {
        size_t idx = 0;
        for (auto itv = dev.internal_values.begin();
             itv != dev.internal_values.end() && idx < MAX_ITEMS;
             ++itv, ++idx) {
            os << "\r\x1B[K    |-- [" << idx << "] value: " << static_cast<unsigned>(*itv) << "\n";
        }
        if (dev.internal_values.size() > MAX_ITEMS) {
            os << "\r\x1B[K    |.. (+" << (dev.internal_values.size() - MAX_ITEMS) << " more)\n";
        }
    }

    // dz_internal_info_list（NameFixValue 描述，和 internal_values 对应）
    os << "\r\x1B[K|-- Internal Value Descriptions (" << dev.dz_internal_info_list.size() << "):\n";
    {
        const size_t n = dev.dz_internal_info_list.size();
        for (size_t i = 0; i < n && i < MAX_ITEMS; ++i) {
            const auto& nf = dev.dz_internal_info_list[i];
            os << "\r\x1B[K    |-- [" << i << "] "
               << "Name="     << trim_cstr(nf.sFixValueName, sizeof(nf.sFixValueName))
               << ", Type="    << nf.DataType
               << ", Unit="    << trim_cstr(nf.sDimension, sizeof(nf.sDimension))
               << ", Min="     << nf.MinValue
               << ", Max="     << nf.MaxValue
               << ", Default=" << nf.DefaultValue
               << "\n";
        }
        if (n > MAX_ITEMS) {
            os << "\r\x1B[K    |.. (+" << (n - MAX_ITEMS) << " more)\n";
        }
    }

    // control_words（控制字描述）
    os << "\r\x1B[K|-- Control Words (" << dev.control_words.size() << "):\n";
    {
        const size_t n = dev.control_words.size();
        for (size_t i = 0; i < n && i < MAX_ITEMS; ++i) {
            const DZ_kzz_bit& b = dev.control_words[i];
            os << "\r\x1B[K    |-- [" << i << "] "
               << "name=\"" << trim_cstr(b.kzz_bit, sizeof(b.kzz_bit)) << "\""
               << ", enable=" << static_cast<int>(b.bit_enable) << "\n";
        }
        if (n > MAX_ITEMS) {
            os << "\r\x1B[K    |.. (+" << (n - MAX_ITEMS) << " more)\n";
        }
    }

    // ========================= 监测点级 · line =========================
    for (size_t i = 0; i < dev.line.size(); ++i) {
        const auto& ld = dev.line[i];
        if (ld.monitor_id.empty()) continue;

        os << "\r\x1B[K|-- line[" << i << "]:\n";
        os << "\r\x1B[K    |-- monitor_id         : " << ld.monitor_id         << "\n";
        os << "\r\x1B[K    |-- monitor_name       : " << ld.monitor_name       << "\n";
        os << "\r\x1B[K    |-- logical_device_seq : " << ld.logical_device_seq << "\n";
        os << "\r\x1B[K    |-- terminal_id        : " << ld.terminal_id        << "\n";
        os << "\r\x1B[K    |-- voltage_level      : " << ld.voltage_level      << "\n";
        os << "\r\x1B[K    |-- terminal_connect   : " << ld.terminal_connect   << "\n";
        os << "\r\x1B[K    |-- status             : " << ld.status             << "\n";
        os << "\r\x1B[K    |-- timestamp          : " << ld.timestamp          << "\n";
        os << "\r\x1B[K    |-- loglevel           : " << ld.LineLogLevel       << "\n";
        os << "\r\x1B[K    |-- CT1=" << ld.CT1 << ", CT2=" << ld.CT2
           << ", PT1=" << ld.PT1 << ", PT2=" << ld.PT2 << "\n";

        // --- 监测点 · 定值（set_values） ---
        os << "\r\x1B[K    |-- Set Values (" << ld.set_values.size() << "):\n";
        {
            size_t idx = 0;
            for (auto it = ld.set_values.begin();
                 it != ld.set_values.end() && idx < MAX_ITEMS;
                 ++it, ++idx) {
                os << "\r\x1B[K        |-- [" << idx << "] " << *it << "\n";
            }
            if (ld.set_values.size() > MAX_ITEMS) {
                os << "\r\x1B[K        |.. (+" << (ld.set_values.size() - MAX_ITEMS) << " more)\n";
            }
        }

        // --- 监测点 · 定值描述文件（dz_info_list） ---
        os << "\r\x1B[K    |-- DZ Table (" << ld.dz_info_list.size() << "):\n";
        {
            const size_t n = ld.dz_info_list.size();
            for (size_t j = 0; j < n && j < MAX_ITEMS; ++j) {
                const DZ_TAB_STRUCT& z = ld.dz_info_list[j];
                os << "\r\x1B[K        |-- [" << j << "] "
                   << "LN=" << z.LN_Num
                   << ", DZ=" << z.DZ_Num
                   << ", Name=" << trim_cstr(z.DZ_Name, sizeof(z.DZ_Name))
                   << ", Type=" << z.DZ_Type
                   << ", Min="  << z.DZ_Min
                   << ", Max="  << z.DZ_Max
                   << ", Def="  << z.DZ_Default
                   << ", Unit=" << trim_cstr(z.DZ_UNIT, sizeof(z.DZ_UNIT))
                   << "\n";
            }
            if (n > MAX_ITEMS) {
                os << "\r\x1B[K        |.. (+" << (n - MAX_ITEMS) << " more)\n";
            }
        }

        // --- 监测点 · 暂态事件（qvvrevent） ---
        os << "\r\x1B[K    |-- QVVR Event:\n";

        // 1) 暂态事件列表
        os << "\r\x1B[K        |-- Events (" << ld.qvvrevent.qvvrdata.size() << "):\n";
        {
            const size_t n = ld.qvvrevent.qvvrdata.size();
            for (size_t k = 0; k < n && k < MAX_ITEMS; ++k) {
                const qvvr_data& e = ld.qvvrevent.qvvrdata[k];
                os << "\r\x1B[K            |-- [" << k << "] "
                   << "used=" << e.used_status
                   << ", type=" << e.QVVR_type
                   << ", time=" << static_cast<unsigned long long>(e.QVVR_time)
                   << ", per="  << e.QVVR_PerTime
                   << ", amp="  << e.QVVR_Amg
                   << ", phase="<< e.phase
                   << "\n";
            }
            if (n > MAX_ITEMS) {
                os << "\r\x1B[K            |.. (+" << (n - MAX_ITEMS) << " more)\n";
            }
        }

        // 2) 文件组列表
        os << "\r\x1B[K        |-- File Groups (" << ld.qvvrevent.qvvrfile.size() << "):\n";
        {
            const size_t n = ld.qvvrevent.qvvrfile.size();
            for (size_t g = 0; g < n && g < MAX_ITEMS; ++g) {
                const qvvr_file& fg = ld.qvvrevent.qvvrfile[g];
                os << "\r\x1B[K            |-- [" << g << "] "
                   << "used=" << fg.used_status
                   << ", tcount=" << fg.file_time_count
                   << ", downloaded=" << fg.is_download
                   << ", paired=" << fg.is_pair
                   << "\n";

                // 文件名列表（file_name）
                os << "\r\x1B[K               |-- file_name (" << fg.file_name.size() << "):\n";
                {
                    size_t c = 0;
                    for (const auto& fn : fg.file_name) {
                        if (c++ >= MAX_ITEMS) break;
                        os << "\r\x1B[K                   |-- " << fn << "\n";
                    }
                    if (fg.file_name.size() > MAX_ITEMS) {
                        os << "\r\x1B[K                   |.. (+" << (fg.file_name.size() - MAX_ITEMS) << " more)\n";
                    }
                }

                // 已下载列表（file_download）
                os << "\r\x1B[K               |-- file_download (" << fg.file_download.size() << "):\n";
                {
                    size_t c = 0;
                    for (const auto& fn : fg.file_download) {
                        if (c++ >= MAX_ITEMS) break;
                        os << "\r\x1B[K                   |-- " << fn << "\n";
                    }
                    if (fg.file_download.size() > MAX_ITEMS) {
                        os << "\r\x1B[K                   |.. (+" << (fg.file_download.size() - MAX_ITEMS) << " more)\n";
                    }
                }
            }
            if (n > MAX_ITEMS) {
                os << "\r\x1B[K            |.. (+" << (n - MAX_ITEMS) << " more)\n";
            }
        }

        // ========================= ★新增：补招打印 =========================
        // ★新增：小工具—把状态/阶段枚举转成可读字符串
        auto recallStatusStr = [](int st) -> const char* {
            switch (st) {
                case 0: return "NOT_STARTED(0)";
                case 1: return "RUNNING(1)";
                case 2: return "DONE(2)";
                case 3: return "FAILED(3)";
                case 4: return "EMPTY(4)";
                default: return "UNKNOWN";
            }
        };
        auto phaseStr = [](RecallPhase p) -> const char* {
            switch (p) {
                case RecallPhase::IDLE:        return "IDLE";
                case RecallPhase::LISTING:     return "LISTING";
                case RecallPhase::DOWNLOADING: return "DOWNLOADING";
            }
            return "UNKNOWN";
        };
        auto resultStr = [](ActionResult r) -> const char* {
            switch (r) {
                case ActionResult::PENDING: return "PENDING";
                case ActionResult::FAIL:    return "FAIL";
                case ActionResult::OK:      return "OK";
            }
            return "UNKNOWN";
        };

        // --- ★新增：事件补招（RecallMonitor） ---
        os << "\r\x1B[K    |-- Recall(Event) (" << ld.recall_list.size() << "):\n";
        {
            size_t idx = 0;
            for (const auto& r : ld.recall_list) {
                if (idx++ >= MAX_ITEMS) break;
                os << "\r\x1B[K        |-- [" << (idx-1) << "] "
                   << "status=" << recallStatusStr(r.recall_status)
                   << ", StartTime=" << r.StartTime
                   << ", EndTime="   << r.EndTime
                   << ", STEADY="    << r.STEADY
                   << ", VOLTAGE="   << r.VOLTAGE
                   << "\n";
            }
            if (ld.recall_list.size() > MAX_ITEMS) {
                os << "\r\x1B[K        |.. (+" << (ld.recall_list.size() - MAX_ITEMS) << " more)\n";
            }
        }

        // --- ★新增：稳态补招（RecallFile）+ 状态机信息 ---
        os << "\r\x1B[K    |-- Recall(Static Files) (" << ld.recall_list_static.size() << "):\n";
        {
            size_t idx = 0;
            for (const auto& rf : ld.recall_list_static) {
                if (idx++ >= MAX_ITEMS) break;
                os << "\r\x1B[K        |-- [" << (idx-1) << "] "
                   << "status=" << recallStatusStr(rf.recall_status)
                   << ", StartTime=" << rf.StartTime
                   << ", EndTime="   << rf.EndTime
                   << ", STEADY="    << rf.STEADY
                   << ", VOLTAGE="   << rf.VOLTAGE
                   << "\n";

                // ★新增：直下模式与目标时间列表
                os << "\r\x1B[K           |-- direct_mode=" << (rf.direct_mode ? "true" : "false")
                   << ", target_filetimes(" << rf.target_filetimes << ")\n";
                {
                    os << "\r\x1B[K               |.. " << rf.target_filetimes << "\n";
                }

                // ★新增：状态机运行态
                os << "\r\x1B[K           |-- phase=" << phaseStr(rf.phase)
                   << ", cur_dir_index=" << rf.cur_dir_index
                   << ", cur_dir=" << rf.cur_dir << "\n";
                os << "\r\x1B[K           |-- list_result=" << resultStr(rf.list_result)
                   << ", download_result=" << resultStr(rf.download_result) << "\n";

                // ★新增：候选目录
                os << "\r\x1B[K           |-- dir_candidates(" << rf.dir_candidates.size() << ")\n";
                {
                    size_t c = 0;
                    for (const auto& d : rf.dir_candidates) {
                        if (c++ >= MAX_ITEMS) break;
                        os << "\r\x1B[K               |-- " << d << "\n";
                    }
                    if (rf.dir_candidates.size() > MAX_ITEMS) {
                        os << "\r\x1B[K               |.. (+" << (rf.dir_candidates.size() - MAX_ITEMS) << " more)\n";
                    }
                }

                // ★新增：目录 -> 文件名列表（仅概要）
                os << "\r\x1B[K           |-- dir_files(" << rf.dir_files.size() << " dirs)\n";
                {
                    size_t c = 0;
                    for (const auto& kv : rf.dir_files) {
                        if (c++ >= MAX_ITEMS) break;
                        os << "\r\x1B[K               |-- [" << (c-1) << "] dir=" << kv.first
                           << " files=" << kv.second.size() << "\n";
                    }
                    if (rf.dir_files.size() > MAX_ITEMS) {
                        os << "\r\x1B[K               |.. (+" << (rf.dir_files.size() - MAX_ITEMS) << " more)\n";
                    }
                }

                // ★新增：下载队列（概要）
                os << "\r\x1B[K           |-- download_queue(" << rf.download_queue.size() << ")\n";
                {
                    size_t c = 0;
                    for (const auto& path : rf.download_queue) {
                        if (c++ >= MAX_ITEMS) break;
                        os << "\r\x1B[K               |-- " << path << "\n";
                    }
                    if (rf.download_queue.size() > MAX_ITEMS) {
                        os << "\r\x1B[K               |.. (+" << (rf.download_queue.size() - MAX_ITEMS) << " more)\n";
                    }
                }

                // ★新增：当前下载中文件
                if (!rf.downloading_file.empty()) {
                    os << "\r\x1B[K           |-- downloading: " << rf.downloading_file << "\n";
                }
            }
            if (ld.recall_list_static.size() > MAX_ITEMS) {
                os << "\r\x1B[K        |.. (+" << (ld.recall_list_static.size() - MAX_ITEMS) << " more)\n";
            }
        }
        // ======================= ★新增：补招打印结束 =======================
    }

    os << "\r\x1B[K------------------------------------\n";
    sendStr(fd, os.str());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////打印所有的终端列表

void Worker::ledger(const std::string& terminal_id, int fd) {
    sendStr(fd, "\r\x1B[Kprint ledger in shell\n");
    std::lock_guard<std::mutex> lock(ledgermtx);
    bool found = false;

    if (terminal_id.empty()) {
        for (const auto& dev : terminal_devlist) {
            printLedgerinshell(dev, fd);
        }
    } else {
        for (const auto& dev : terminal_devlist) {
            if (dev.terminal_id == terminal_id) {
                printLedgerinshell(dev, fd);
                found = true;
                break;
            }
        }

        if (!found) {
            std::ostringstream msg;
            msg << "\r\x1B[Kterminal not exist: " << terminal_id << "\n";
            sendStr(fd, msg.str());
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////打印指定的变量名

void Worker::value_print(const std::string& variableName, int clientFD) {
    std::string output;

    {
        std::lock_guard<std::mutex> lock(ledgermtx);
        std::cout << "value_print hold lock !!!!!!!!!!!" << std::endl;

        if (variableName == "frontindex") {
            output = "frontindex = " + std::to_string(g_front_seg_index);
        } else if (variableName == "iedcount") {
            output = "ledger list = " + std::to_string(terminal_devlist.size()) +
                     ", ied config count = " + std::to_string(IED_COUNT);
        } else if (variableName == "frontfun") {
            output = "frontfun = " + subdir;
        } else if (variableName == "log") {
            output = "showinshellflag = " + std::to_string(showinshellflag) +
                     ", normalOutputEnabled = " + std::to_string(normalOutputEnabled) +
                     ", warnOutputEnabled = " + std::to_string(warnOutputEnabled) +
                     ", errorOutputEnabled = " + std::to_string(errorOutputEnabled);
        } else if (variableName == "init") {
            output = "INITFLAG = " + std::to_string(INITFLAG);
        } else {
            output = "Unknown variable name: " + variableName;
        }

        std::cout << "value_print free lock !!!!!!!!!!!" << std::endl;
    }

    sendStr(clientFD, "\r\x1B[K" + output + "\r\n");
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////日志开关控制

//日志消息列表
std::list<std::string>* getLogList(const std::string& level) {
    if (level == "ERROR") return &errorList;
    if (level == "WARN") return &warnList;
    if (level == "NORMAL") return &normalList;
    return nullptr;
}

//日志锁
std::mutex* getLogMutex(const std::string& level) {
    if (level == "ERROR") return &errorListMutex;
    if (level == "WARN") return &warnListMutex;
    if (level == "NORMAL") return &normalListMutex;
    return nullptr;
}

void Worker::handleViewLogCommand(const std::string& command, int clientFD) {
    std::istringstream iss(command);
    std::string cmd, level;
    iss >> cmd >> level;
    std::transform(level.begin(), level.end(), level.begin(), ::toupper);

    if (level.empty()) {
        sendStr(clientFD, "\r\x1B[KUsage: viewlog [ERROR|WARN|NORMAL]\r\n> ");
        return;
    }

    std::list<std::string>* logList = getLogList(level);
    std::mutex* logMutex = getLogMutex(level);

    if (!logList || !logMutex) {
        sendStr(clientFD, "\r\x1B[KInvalid log level! Use ERROR, WARN, NORMAL.\r\n> ");
        return;
    }

    stopViewLog = false;
    showinshellflag = true;
    sendStr(clientFD, std::string("\r\x1B[KViewing logs for level: ") + level + " (Press '`' to exit)\r\n> ");

    char inputBuf[16];

    // --- 新增 begin: 目录创建 + 唯一文件名生成 + 打开文件 ---
    // 递归创建目录的小工具（最小实现，按‘/’逐级创建）
    auto ensure_dir = [](const std::string& path) -> bool {
        if (path.empty()) return false;
        std::string cur;
        cur.reserve(path.size());
        for (size_t i = 0; i < path.size(); ++i) {
            cur.push_back(path[i]);
            if (path[i] == '/' && cur.size() > 1) {
                if (::access(cur.c_str(), F_OK) != 0) {
                    if (::mkdir(cur.c_str(), 0755) != 0 && errno != EEXIST) return false;
                }
            }
        }
        // 末级（若不以 / 结尾）
        if (cur.back() != '/') {
            if (::access(cur.c_str(), F_OK) != 0) {
                if (::mkdir(cur.c_str(), 0755) != 0 && errno != EEXIST) return false;
            }
        }
        return true;
    };

    const std::string logDir = "/FeProject/dat/log";
    if (!ensure_dir(logDir)) {
        sendStr(clientFD, "\r\x1B[KFailed to create log directory: /FeProject/dat/log\r\n> ");
        return;
    }

    std::string filePath = logDir + "/temp.log";
    int index = 1;
    while (::access(filePath.c_str(), F_OK) == 0) {
        filePath = logDir + "/temp_" + std::to_string(index++) + ".log";
    }

    std::ofstream logFile(filePath.c_str(), std::ios::out | std::ios::trunc);
    if (!logFile.is_open()) {
        sendStr(clientFD, "\r\x1B[KFailed to open log file for writing.\r\n> ");
        return;
    }
    // --- 新增 end ---

    while (!stopViewLog) {
        // 1) 监听 shell 输入退出符号 `
        fd_set read_fds;
        FD_ZERO(&read_fds);
        FD_SET(clientFD, &read_fds);

        timeval timeout;
        timeout.tv_sec = 0;
        timeout.tv_usec = 500000; // 500ms

        int activity = select(clientFD + 1, &read_fds, nullptr, nullptr, &timeout);
        if (activity > 0 && FD_ISSET(clientFD, &read_fds)) {
            int n = recv(clientFD, inputBuf, sizeof(inputBuf), 0);
            if (n > 0 && std::memchr(inputBuf, '`', static_cast<size_t>(n))) {
                stopViewLog = true;
                showinshellflag = false;
                break;
            }
        }

        // --- 修改 begin: 批量获取日志（swap 全取，减少加锁时间） ---
        std::list<std::string> tempLogs;
        {
            std::lock_guard<std::mutex> lock(*logMutex);
            if (!logList->empty()) {
                tempLogs.swap(*logList);  // 把 logList 中的内容全取出
            }
        }
        // --- 修改 end ---

        if (!tempLogs.empty()) {
            for (const auto& logEntry : tempLogs) {
                if (!logEntry.empty()) {
                    sendStr(clientFD, std::string("\r\x1B[K") + logEntry + "\r\n");

                    // --- 新增 begin: 写入文件 + 及时落盘 ---
                    logFile << logEntry << '\n';
                    // --- 新增 end ---
                }
            }
            // --- 新增 begin: 刷新文件缓冲，保证实时可见 ---
            logFile.flush();
            // --- 新增 end ---
        } else {
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }
    }

    // 3) 打印退出提示
    sendStr(clientFD, "\r\x1B[K\nLog view stopped. Returning to shell.\r\n> ");

    // --- 新增 begin: 关闭文件 ---
    logFile.close();
    // --- 新增 end ---
}


