#include "HttpEntity.h"
#include "database/Dao.h"
#include <functional>
#include "common/Utils.h"
#include "common/Snowflake.h"
#include "app/Application.h"
#include "app/AppData.h"
#include "app/Config.h"
#include "app/Station.h"
#include "app/Device.h"
#include "common/XlsxEntity.h"

static void FieldsToJson(Fields& fields, njson& json)
{
    for (auto& item : fields.map())
    {
        json[item.first] = item.second;
    }
}
static void JsonToFields(njson& json, std::vector<std::string> vecKeys, Fields& fields)
{
    if (vecKeys.empty())
    {
        for (auto& item: json.items())
        {
            auto key = item.key();
            auto& val = json[key];
        }
    }

    for (auto& key : vecKeys)
    {
        if (json.contains(key)) {

            switch (json[key].type())
            {
            case njson::value_t::string: { fields.set(key, json[key].get<std::string>()); } break;
            case njson::value_t::boolean: { fields.set(key, json[key].get<bool>()); } break;
            case njson::value_t::number_integer: { fields.set(key, json[key].get<int>()); } break;
            case njson::value_t::number_unsigned: { fields.set(key, json[key].get<int>()); } break;
            case njson::value_t::number_float: { fields.set(key, json[key].get<float>()); } break;
            case njson::value_t::null: {} break;
            case njson::value_t::object: { fields.set(key, json[key].dump()); } break;
            case njson::value_t::array: { fields.set(key, json[key].dump()); } break;
            case njson::value_t::binary: {} break;
            case njson::value_t::discarded: {} break;
            default:
                break;
            }
        }
    }
}

static njson FieldsToJsonArray(std::vector<Fields>& vecFields)
{
    njson jsonnode = njson::array();
    for (auto& fields : vecFields)
    {
        njson jnode;
        for (auto& item : fields.map())
        {
            jnode[item.first] = item.second;
        }
        jsonnode.push_back(jnode);
    }
    return jsonnode;
}

static void GetRequestParams(const httplib::Request& req, const std::vector<std::string>& vecKeys, Fields& fields)
{
    if (req.method == "GET")
    {
        for (auto& key : vecKeys)
        {
            if (req.has_param(key))
            {
                fields.set(key, req.get_param_value(key));
            }
        }
    }
    else if (req.method == "POST")
    {
        njson json;
        JSON::parse(req.body, json);
        JsonToFields(json, vecKeys, fields);
    }
}

static void CheckRequiredParams(Fields& params, std::vector<std::string> keys, std::string& errmsg)
{
    for (auto& key : keys)
    {
        if (!params.contains(key)) 
        { 
            errmsg = "参数[" + key + "]错误";;
            return; 
        }
    }
}

class HttpHelper
{
public:
    static bool CheckRequestParam(const httplib::Request& req, httplib::Response& resp, const std::vector<std::string>& vecKeys, std::string& errmsg)
    {
        errmsg = "";
        for (auto& key : vecKeys)
        {
            bool hasParam = false;
            if (req.method == "GET") 
            { 
                hasParam = req.has_param(key); 
            }
            else
            { 
                hasParam = (req.body.find("\"" + key  + "\"") != std::string::npos);
            }
            if (!hasParam) 
            { 
                if (!errmsg.empty()) { errmsg += ","; }
                errmsg += "缺少参数[" + key + "]"; 
            }
        }
        if (!errmsg.empty())
        {
            return false;
        }
        return true;
    }
    static void setPagination(PageInfo& pageinfo, std::vector<Fields> result, njson& json)
    {
        json["count"] = pageinfo.total;
        json["page"] = pageinfo.index;
        json["page_size"] = pageinfo.size;
        json["data"] = FieldsToJsonArray(result);
    }
};



static std::map<std::string, HandlerOptions> g_mapHttpHandlerGet =
{
    {"/queryBaseinfo", HandlerOptions(&HttpEntity::logqueryBaseinfoin, {})},

    {"/login", HandlerOptions(&HttpEntity::login, {DMUser::ACCOUNT, DMUser::PASSWD})},
    {"/queryUserList", HandlerOptions(&HttpEntity::queryUserList, {})},
    {"/deleteUser", HandlerOptions(&HttpEntity::deleteUser, { DMUser::USER_ID})},
    
    {"/queryPermissionList", HandlerOptions(&HttpEntity::queryPermissionList, {})},
    {"/deletePermission", HandlerOptions(&HttpEntity::deletePermission, { DMPermission::PERMISSION_ID})},
    
    {"/queryRoleList", HandlerOptions(&HttpEntity::queryRoleList, {})},
    {"/deleteRole", HandlerOptions(&HttpEntity::deleteRole, { DMRole::ROLE_ID})},
    
    {"/queryStationList", HandlerOptions(&HttpEntity::queryStationList, {})},
    {"/deleteStation", HandlerOptions(&HttpEntity::deleteStation, { DMStation::STATION_ID})},

    {"/queryStationInfo", HandlerOptions(&HttpEntity::queryStationInfo, { DMStation::STATION_ID})},
    {"/queryStationData", HandlerOptions(&HttpEntity::queryStationData, { DMStation::STATION_ID})},
    {"/queryStationOverview", HandlerOptions(&HttpEntity::queryStationOverview, {DMStation::STATION_ID})},

    {"/queryStationTodayU", HandlerOptions(&HttpEntity::queryStationTodayU, {DMStation::STATION_ID, "category"})},
    {"/queryStationTodayI", HandlerOptions(&HttpEntity::queryStationTodayI, {DMStation::STATION_ID, "category"})},
    {"/queryStationTodayP", HandlerOptions(&HttpEntity::queryStationTodayP, {DMStation::STATION_ID, "category"})},

    {"/queryDeviceList", HandlerOptions(&HttpEntity::queryDeviceList, {})},
    {"/deleteDevice", HandlerOptions(&HttpEntity::deleteDevice, { DMDevice::DEVICE_ID})},
    {"/queryDevicTypeDef", HandlerOptions(&HttpEntity::queryDevicTypeDef, {})},
    {"/queryDevicByCategory", HandlerOptions(&HttpEntity::queryDevicByCategory, {DMStation::STATION_ID, "category"})},
    {"/queryDevicCharts", HandlerOptions(&HttpEntity::queryDevicCharts, {DMStation::STATION_ID, "device_id"})},
    {"/queryDeviceBCUDetail", HandlerOptions(&HttpEntity::queryDeviceBCUDetail, {DMStation::STATION_ID, "device_id"})},
    

    {"/queryPolicyList", HandlerOptions(&HttpEntity::queryPolicyList, {})},
    {"/deletePolicy", HandlerOptions(&HttpEntity::deletePolicy, { DMPolicy::POLICY_ID})},
    {"/queryPolicyByType", HandlerOptions(&HttpEntity::queryPolicyByType, {"type"})},

    {"/querySystemLogList", HandlerOptions(&HttpEntity::querySystemLogList, {})},
    
    {"/queryAlertLogList", HandlerOptions(&HttpEntity::queryAlertLogList, {})},

    {"/queryPredictionDetail", HandlerOptions(&HttpEntity::queryPredictionDetail, {})},
    
    {"/queryStatSystem", HandlerOptions(&HttpEntity::queryStatSystem, {})},
    {"/queryStatStation", HandlerOptions(&HttpEntity::queryStatStationGroup, {})},
    {"/queryStatTotal", HandlerOptions(&HttpEntity::queryStatTotal, {})},
    {"/queryStatDayList", HandlerOptions(&HttpEntity::queryStatDayList, {})},
    {"/queryStatDetailList", HandlerOptions(&HttpEntity::queryStatDetailList, {})},
    {"/queryStatCharts", HandlerOptions(&HttpEntity::queryStatCharts, {})},
    {"/exportStatReport", HandlerOptions(&HttpEntity::exportStatReport, {})},

    {"/queryEnvironment", HandlerOptions(&HttpEntity::queryEnvironment, { "station_id"})},

    {"/queryServiceApiList", HandlerOptions(&HttpEntity::queryServiceApiList, {})},
    {"/deleteServiceApi", HandlerOptions(&HttpEntity::deleteServiceApi, {"api_id"})},

    {"/queryEGridPeriod", HandlerOptions(&HttpEntity::queryEGridPeriod, {})},

    //{"/insert", HandlerOptions(&HttpEntity::insert, {})},
    //{"/update", HandlerOptions(&HttpEntity::update, {})},
    //{"/delete", HandlerOptions(&HttpEntity::delete, {})},
};

static std::map<std::string, HandlerOptions> g_mapHttpHandlerPost
{
    {"/insertUser", HandlerOptions(&HttpEntity::insertUser, { DMUser::ACCOUNT})},
    {"/updateUser", HandlerOptions(&HttpEntity::updateUser, { DMUser::USER_ID})},

    {"/insertPermission", HandlerOptions(&HttpEntity::insertPermission, { DMPermission::NAME})},
    {"/updatePermission", HandlerOptions(&HttpEntity::updatePermission, { DMPermission::PERMISSION_ID})},

    {"/insertRole", HandlerOptions(&HttpEntity::insertRole, { DMRole::NAME})},
    {"/updateRole", HandlerOptions(&HttpEntity::updateRole, { DMRole::ROLE_ID})},

    {"/insertStation", HandlerOptions(&HttpEntity::insertStation, { DMStation::NAME})},
    {"/updateStation", HandlerOptions(&HttpEntity::updateStation, { DMStation::STATION_ID})},

    {"/insertDevice", HandlerOptions(&HttpEntity::insertDevice, { DMDevice::NAME})},
    {"/updateDevice", HandlerOptions(&HttpEntity::updateDevice, { DMDevice::DEVICE_ID})},

    {"/insertPolicy", HandlerOptions(&HttpEntity::insertPolicy, { DMPolicy::NAME})},
    {"/updatePolicy", HandlerOptions(&HttpEntity::updatePolicy, { DMPolicy::POLICY_ID})},

    {"/insertServiceApi", HandlerOptions(&HttpEntity::insertServiceApi, {})},
    {"/updateServiceApi", HandlerOptions(&HttpEntity::updateServiceApi, {"api_id"})},

    {"/updateGatewayParams", HandlerOptions(&HttpEntity::updateGatewayParams, {DMStation::STATION_ID})},
};

bool CheckHttpToken(const httplib::Request& req)
{
    // 验证token
    std::string token = req.get_param_value("token");
    if (!token.empty())
    {
        User user = Application::data().getUser(token);
        if (!user.userId.empty())
        {
            return true;
        }
    }
    return false;
}


HttpEntity::HttpEntity()
{
    for (auto& item : g_mapHttpHandlerGet)
    {
        std::string name = item.first;
        HandlerOptions& handler = item.second;
        this->httpsvr.Get(name, [=, &handler](const httplib::Request& req, httplib::Response& resp)
            {
                this->runHandler(name, handler, req, resp);
            });
    }
    for (auto& item : g_mapHttpHandlerPost)
    {
        std::string name = item.first;
        HandlerOptions& handler = item.second;
        this->httpsvr.Post(name, [=](const httplib::Request& req, httplib::Response& resp)
            {
                this->runHandler(name, handler, req, resp);
            });
    }
}

void HttpEntity::listen(std::string addr, int port)
{
    if (addr.empty()) addr = "0.0.0.0";
    spdlog::info("[http] start listen: addr={}:{},token={}", addr, port, Config::option.http.useToken);
    httpsvr.listen(addr, port); // 阻塞
}

void HttpEntity::runHandler(std::string name, const HandlerOptions& handler, const httplib::Request& req, httplib::Response& resp)
{
    spdlog::info("[http] request: {}", name);
    bool useToken = Config::option.http.useToken;
    Errcode errcode = Errcode::OK;
    std::string errmsg;

    if (name != "/login" && useToken)
    {
        bool ret = CheckHttpToken(req);
        errcode = ret ? Errcode::OK : Errcode::ERR_TOKEN;
    }

    njson jsonresp;
    if (errcode == Errcode::OK)
    {
        if (!HttpHelper::CheckRequestParam(req, resp, handler.requiredKeys, errmsg))
        {
            errcode = Errcode::ERR_PARAM;
        }
        else
        {
            errcode = (this->*(handler.func))(req, jsonresp, errmsg);
        }
    }
    jsonresp["errcode"] = errcode;
    jsonresp["errmsg"] = ErrcodeStr(errcode) + (errmsg.empty() ? "" : (":"+errmsg));
    resp.set_content(jsonresp.dump(), "text/plain; charset=utf-8");
    resp.status = 200;
    spdlog::info("[http] request: {}, response: {}.", name, int(errcode));
}

void HttpEntity::registGet(std::string name, void (HttpEntity::* func)(const httplib::Request& req, httplib::Response& resp))
{
    this->httpsvr.Get(name, std::bind(func, this, std::placeholders::_1, std::placeholders::_2));
}

Errcode HttpEntity::logqueryBaseinfoin(const httplib::Request& req, njson& json, std::string& errmsg)
{
    json["data"] = {
        {"encryption", Config::option.http.encryption},
        {"encryptKey", Config::option.http.encryptKey},
        {"latitude", Config::option.view.latitude},
        {"longitude", Config::option.view.longitude},
        {"altitude", Config::option.view.altitude}
    };
    return Errcode::OK;
}

Errcode HttpEntity::login(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string userId;
    std::string token;
    std::string account = req.get_param_value("account");
    std::string passwd = req.get_param_value("passwd");
    
    Fields fields;
    auto dao = DaoEntity::create("");
    Errcode err = DAO::login(dao, account, passwd, fields);
    userId = fields.value(DMUser::USER_ID);
    token = Application::data().userLogin(userId, account);
    if (err == Errcode::OK)
    {
        json["token"] = token;
        json["account"] = account;

        std::vector<Fields> vecPermission;
        int roleId = fields.get<int>(DMRole::ROLE_ID);
        DAO::queryRolePermission(dao, roleId, vecPermission);

        njson nodePermission = njson::array();
        std::map<std::string, int> mapParentPos;
        for (int i=0; i<vecPermission.size(); ++i)
        {
            auto& item = vecPermission[i];
            if (item.value("parent_id") == "")
            {
                mapParentPos[item.value("permission_id")] = i;
                njson node;
                FieldsToJson(item, node);
                node["children"] = njson::array();
                nodePermission.push_back(node);
            }
        }
        // 重新遍历处理二级子权限，防止父权限信息还未创建时导致错误
        for (int i = 0; i<vecPermission.size(); ++i)
        {
            auto& item = vecPermission[i];
            std::string id = item.value("permission_id");
            std::string parentId = item.value("parent_id");
            if (parentId != "")
            {
                auto iter = mapParentPos.find(parentId);
                if (iter != mapParentPos.end())
                {
                    njson node;
                    FieldsToJson(item, node);
                    nodePermission[iter->second]["children"].push_back(node);
                }
            }
        }
        json["permission"] = nodePermission;
    }

    DAO::insertSystemLogUser(token, "用户[" + account + "]登录：" + ErrcodeStr(err), (err==Errcode::OK) ? 1: 0);
    return err;
}

Errcode HttpEntity::queryUserList(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string token = req.get_param_value("token");
    PageInfo pageinfo;
    pageinfo.index = Utils::toInt(req.get_param_value("page"));
    pageinfo.size = Utils::toInt(req.get_param_value("page_size"));

    std::vector<Fields> result;
    auto err = DAO::queryUserList(pageinfo, result);
    if (err == Errcode::OK)
    {
        HttpHelper::setPagination(pageinfo, result, json);
    }
    //DAO::insertSystemLogUser(token, "查询用户列表：" + ErrcodeStr(err), (err==Errcode::OK) ? 1 : 0);
    return err;
}

Errcode HttpEntity::insertUser(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"account", "name", "gender", "age", "phone", "email", "role_id"}, params);
    return DAO::insertUser(params);
}

Errcode HttpEntity::updateUser(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"user_id", "account", "name", "gender", "age", "phone", "email", "role_id"}, params);
    return DAO::updateUserById(params);
}

Errcode HttpEntity::deleteUser(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string userId = req.get_param_value("user_id");
    return DAO::deleteUserById(userId);
}

Errcode HttpEntity::queryPermissionList(const httplib::Request& req, njson& json, std::string& errmsg)
{
    PageInfo pageinfo;
    pageinfo.index = Utils::toInt(req.get_param_value("page"));
    pageinfo.size = Utils::toInt(req.get_param_value("page_size"));

    std::vector<Fields> result;
    auto err = DAO::queryPermissionList(pageinfo, result);
    HttpHelper::setPagination(pageinfo, result, json);

    // 查询所有的角色权限关联
    if (err == Errcode::OK)
    {
        std::map<std::string, int> mapP;
        for (int i = 0; i<result.size(); ++i)
        {
            auto& item = result[i];
            std::string id = item.value("permission_id");
            mapP[id] = json["data"].size() - 1;
        }

        std::vector<Fields> vecSubPermission;
        DaoEntity::execOnce("SELECT * FROM permission WHERE permission.parent_id IS NOT NULL AND permission.parent_id!='';", vecSubPermission);
        
        for (int i = 0; i<vecSubPermission.size(); ++i)
        {
            auto& item = vecSubPermission[i];
            std::string parentId = item.value("parent_id");
            std::string id = item.value("permission_id");
            if (!parentId.empty())
            {
                if (mapP.count(parentId) > 0)
                {
                    int index = mapP[parentId];
                    njson jsonnode;
                    FieldsToJson(item, jsonnode);
                    json["data"][index]["children"].push_back(jsonnode);
                }
            }
        }
    }
    return err;
}

Errcode HttpEntity::insertPermission(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"name", "describe", "is_open"}, params);
    return DAO::insertPermission(params);
}

Errcode HttpEntity::updatePermission(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"permission_id", "name", "describe", "is_open"}, params);
    return DAO::updatePermissionById(params);
}

Errcode HttpEntity::deletePermission(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string permissionId = req.get_param_value("permission_id");
    return DAO::deletePermissionById(permissionId);
}

Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string token = req.get_param_value("page");
    PageInfo pageinfo;
    pageinfo.index = Utils::toInt(req.get_param_value("page"));
    pageinfo.size = Utils::toInt(req.get_param_value("page_size"));

    std::vector<Fields> result;
    auto err = DAO::queryRoleList(pageinfo, result);
    HttpHelper::setPagination(pageinfo, result, json);

    // 查询所有的角色权限关联
    if (err == Errcode::OK)
    {
        std::vector<Fields> vecPermission;
        err = DAO::queryRolePermission(NULL, vecPermission);
        if (err != Errcode::OK)
        {
            return err;
        }

        std::map<std::string, std::vector<int>> mapRole;
        std::map<std::string, std::vector<int>> mapChildren;
        for (int i=0; i<vecPermission.size(); ++i)
        {
            auto& item = vecPermission[i];
            std::string roleId = item.value("role_id");
            std::string parentId = item.value("parent_id");
            mapRole[roleId].push_back(i);
            if (parentId != "")
            {
                mapChildren[roleId + "-" + parentId].push_back(i);
            }
        }

        for (auto& item : json["data"])
        {
            auto jsonpermission = njson::array();
            std::string roleId = item["role_id"];
   
            for (auto& fieldsPos : mapRole[roleId])
            {
                auto& fields = vecPermission[fieldsPos];
                string parentId = fields.value("parent_id");
                string permissionId = fields.value("permission_id");
                if (parentId == "")
                {
                    njson node;
                    FieldsToJson(fields, node);

                    njson nodeChildren = njson::array();
                    auto iter = mapChildren.find(roleId + "-" + permissionId);
                    if (iter != mapChildren.end())
                    {
                        for (auto& fieldsChildPos : iter->second)
                        {
                            njson nodeChild;
                            FieldsToJson(vecPermission[fieldsChildPos], nodeChild);
                            nodeChildren.push_back(nodeChild);
                        }
                    }
                    node["children"] = nodeChildren;
                    jsonpermission.push_back(node);
                }
            }
            item["permission"] = jsonpermission;
        }
    }
    return err;
}

Errcode HttpEntity::queryRolePermission(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"role_id"}, params);
    if (!params.contains("role_id")) { errmsg = "缺少参数[role_id]"; return Errcode::ERR_PARAM; }
    return Errcode::OK;
}

Errcode HttpEntity::insertRole(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"name", "describe", "is_open", "permission"}, params);
    return DAO::insertRole(params);
};


static void JsonToFieldsRole(string roleId, njson& item, Fields& fields)
{
    fields.set("role_id", roleId);
    fields.set("permission_id", item["permission_id"].get<std::string>());
    fields.set("is_open", item["is_open"].get<std::string>());
    fields.set("is_view", item["is_view"].get<std::string>());
    fields.set("is_add", item["is_add"].get<std::string>());
    fields.set("is_edit", item["is_edit"].get<std::string>());
    fields.set("is_del", item["is_del"].get<std::string>());
}

Errcode HttpEntity::updateRole(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"role_id", "name", "describe", "is_open", "permission"}, params);

    auto roleId = params.value("role_id");
    std::string permission = params.remove("permission");
    
    auto dao = DaoEntity::create("");
    auto err = Errcode::OK;
    if (params.size() > 1)
    {
        err = DAO::updateRoleById(dao, params);
    }
    if (err == Errcode::OK && !permission.empty())
    {
        njson jsonarray;
        if (JSON::parse(permission, jsonarray))
        {
            std::vector<Fields> vecFields;
            for (auto& item: jsonarray)
            {
                Fields fields;
                JsonToFieldsRole(roleId, item, fields);
                vecFields.push_back(fields);

                if (item.contains("children"))
                {
                    for (auto& item : item["children"])
                    {
                        Fields fields;
                        JsonToFieldsRole(roleId, item, fields);
                        vecFields.push_back(fields);
                    }
                }
            }
            err = DAO::updateRolePermission(dao, roleId, vecFields);
        }
    }
    return err;
};
Errcode HttpEntity::deleteRole(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string roleId = req.get_param_value(DMRole::ROLE_ID);
    return DAO::remove(NULL, DMRole::TABLENAME, DMRole::ROLE_ID, roleId);
};

Errcode HttpEntity::queryStationList(const httplib::Request& req, njson& json, std::string& errmsg) 
{
    PageInfo pageinfo;
    pageinfo.index = Utils::toInt(req.get_param_value("page"));
    pageinfo.size = Utils::toInt(req.get_param_value("page_size"));

    std::vector<Fields> result;
    auto err = DAO::queryStationList(pageinfo, result);
    for (auto& item : result)
    {
        int stationId = item.get<int>("station_id");
        auto station = Application::data().getStation(stationId);
        if (station)
        {
            item.set("err", station->err);
        }
    }
    HttpHelper::setPagination(pageinfo, result, json);
    return err;
};

Errcode HttpEntity::insertStation(const httplib::Request& req, njson& json, std::string& errmsg)
{
    
    Fields params;
    GetRequestParams(req, {"name", "address", "lon", "lat", "tel", "capacity", "status"}, params);
    return DAO::insertStation(params);
};

Errcode HttpEntity::updateStation(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"station_id", "name", "address", "lon", "lat", "tel", "capacity", "status", "work_mode", "policy_id", "operation_date"}, params);
    std::string stationId = params.value("station_id");
    params.check("capacity", "", "0.0");
    params.check("lon", "", "0.0");
    params.check("lat", "", "0.0");
    params.check("status", "", "1");
    params.check("policy_id", "", "NULL");
    params.check("operation_date", "", "NULL");
    Errcode err = DAO::updateStationById(params);
    if (err == Errcode::OK)
    {
        std::string sql = "SELECT s.*, p.name policy_name, p.`type` policy_type, p.value FROM station s LEFT JOIN policy p ON s.policy_id=p.policy_id"
            " WHERE s.station_id='" + stationId + "';";
        std::vector<Fields> result;
        int ret = DaoEntity::execOnce(sql, result);
        if (ret != 0)
        {
            spdlog::error("[http] update station success, set station cache error, station_id={}", stationId);
        }
        else
        {
            auto station = Application::data().getStation(Utils::toInt(stationId));
            if (result.size() > 0 && station)
            {
                station->setFields(result[0]);
            }
        }
    }
    if (params.contains("station_id") && params.contains("work_mode"))
    {
        int stationId = params.get<int>("station_id");
        int workmode = params.get<int>("work_mode");
        auto station = Application::data().getStation(stationId);
        if (station)
        {
            station->setGarewayWorkMode();
        }
    }
    return err;
};

Errcode HttpEntity::deleteStation(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string primaryKey = DMStation::STATION_ID;
    return DAO::remove(NULL, DMStation::TABLENAME, primaryKey, req.get_param_value(primaryKey));
};

Errcode HttpEntity::queryStationOverview(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"station_id"}, params);
    std::string stationId = params.value("station_id");
    if (stationId.empty()) 
    { 
        return Errcode::ERR_PARAM; 
    }

    auto dao = DaoEntity::create("");
    std::vector<Fields> result;

    // 运行模式
    std::string sql = "SELECT * FROM station WHERE station_id='" + stationId + "';";
    int ret = dao->exec(sql, result);
    if (ret != 0)
    {
        return Errcode(ret);
    }
    if (result.size() > 0)
    {
        json["data"]["work_mode"] = result[0].get<int>("work_mode");
    }

    // 储能设备：总功率，数量
    // 充电设备：总功率，数量
    // 光伏设备：总功率，数量
    sql = R"(SELECT d.`type`, count(1) count, ddt.name typename, ddt.category FROM device d
	    LEFT JOIN def_device_type ddt ON ddt.device_type_id=d.`type` WHERE d.station_id=')" + stationId + "' GROUP BY `type`;";
    ret = dao->exec(sql, result);
    if (ret != 0) 
    {
        return Errcode(ret);
    }
    njson jsonStorage   = njson::parse(R"({"category":1, "count":0, "power":0.0})");
    njson jsonCharge    = njson::parse(R"({"category":2, "count":0, "power":0.0})");
    njson jsonSolar     = njson::parse(R"({"category":3, "count":0, "power":0.0})");
    njson jsonSecurity  = njson::parse(R"({"category":4, "count":0, "power":0.0})");
    //auto station = Application::data().getStation(Utils::toInt(stationId));
    //if (station)
    //{
    //    jsonStorage["msg"] = station->getGatewayParam();
    //    jsonStorage["workmode"] = station->getGatewayMode();
    //    jsonStorage["emu"] = station->emuStatus == 1 ? "在线" : (station->emuStatus == 0 ? "离线" : "--");
    //    jsonStorage["cdz"] = station->cdzStatus == 1 ? "在线" : (station->cdzStatus == 0 ? "离线" : "--");
    //}
    auto videoInfo = Config::getVideoInfo(stationId);
    if (videoInfo)
    {
        jsonSecurity["host"] = videoInfo->host;
        jsonSecurity["port"] = videoInfo->port;
        jsonSecurity["user"] = videoInfo->user;
        jsonSecurity["passwd"] = videoInfo->passwd;
    }

    for (auto& fields : result)
    {
        int category = fields.get<int>("category");
        int count = fields.get<int>("count");
        switch (category)
        {
        case 1: { jsonStorage["count"] = jsonStorage["count"].get<int>() + count; } break;
        case 2: { jsonCharge["count"] = jsonCharge["count"].get<int>() + count; } break;
        case 3: { jsonSolar["count"] = jsonSolar["count"].get<int>() + count; } break;
        case 4: { jsonSecurity["count"] = jsonSecurity["count"].get<int>() + count; } break;
        default:
            break;
        }
    }

    // 从运行数据中读取功率信息（待补充）

    json["data"]["device_group"] = {jsonStorage, jsonCharge, jsonSolar, jsonSecurity};
    return Errcode::OK;
}

Errcode HttpEntity::queryStationInfo(const httplib::Request& req, njson& json, std::string& errmsg)
{
    // 查询场站的基础配置信息
    std::string stationId = req.get_param_value("station_id");
    if (stationId.empty())
    {
        return Errcode::ERR_PARAM;
    }

    std::string sql = "SELECT * FROM " + DMStation::TABLENAME + " WHERE station_id=" + stationId + ";";
    std::vector<Fields> result;
    Errcode err = DAO::exec(NULL, sql, result);
    if (err != Errcode::OK)
    {
        return err;
    }
    if (result.size() == 0)
    {
        return Errcode::ERR_DATA_NUL;
    }
    auto& fields = result[0];

    njson jsondata;
    std::string attr = fields.remove(DMStation::ATTR);
    JSON::parse(attr, jsondata);

    FieldsToJson(fields, jsondata);
    json["data"] = jsondata;
    return Errcode::OK;

    // work_mode: 运行模式：
    // capacity: 储能容量：
    
    // {"batttey_type": "磷酸铁锂", "cooling_type":"风冷", "voltage_rated":"300", "power_rated": "1500"} 
    // batttey_type: 电池类型：
    // cooling_type: 冷却方式：
    // voltage_rated: 电池额定电压：
    // power_rated: PCS额定功率
}
Errcode HttpEntity::queryStationData(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string stationId = req.get_param_value("station_id");
    auto station = Application::data().getStation(Utils::toInt(stationId));
    njson jsondata;
    if (station)
    {
        /// 储能：电压、电流、功率、功率因数
        {
            njson json = njson::object();
            json["U"] = Utils::toStr(station->storage.voltage);
            json["I"] = Utils::toStr(station->storage.current);
            json["P"] = Utils::toStr(station->storage.power);
            //json["PF"] = Utils::toStr(station->storage.powerFactor, 1);
            jsondata["storage"] = json;
        }
        /// 充电：电压、电流、功率、功率因数
        {
            njson json = njson::object();
            json["U"] = Utils::toStr(station->charge.connector1.voltage);
            json["I"] = Utils::toStr(station->charge.connector1.current);
            json["P"] = Utils::toStr(station->charge.connector1.power);
            jsondata["charge"] = json;
        }
        /// 光伏
        {
            njson json = njson::object();
            json["P"] = Utils::toStr(station->pv.power);
            jsondata["pv"] = json;
        }
        /// 电网
        {
            njson json = njson::object();
            json["U"] = Utils::toStr(station->grid.voltage);
            json["I"] = Utils::toStr(station->grid.current);
            json["P"] = Utils::toStr(station->grid.power);
            //json["PF"] = Utils::toStr(station->grid.powerFactor, 1);
            jsondata["grid"] = json;
        }

        /// 环境：温度、湿度
        {
            njson json = njson::object();
            json["envTemp"] = Utils::toStr(station->temperature, 0);
            json["envhum"] = Utils::toStr(station->humidity, 0);
            json["aircStatus"] = station->aircStatus;
            json["coolingStatus"] = station->coolingStatus;
            jsondata["env"] = json;
        }
    }
    json["data"] = jsondata;
    return Errcode::OK;
}

static njson VectorToJsonArray(vector<float>& vec, int n)
{
    njson jsonArray = njson::array();
    for (int i = 0; i <= n && i < vec.size(); ++i)
    {
        jsonArray.push_back(int(vec[i]));
    }
    return jsonArray;
}

// 获取场站今日电压曲线数据，category: 1：储能，2：充电，3：光伏
Errcode HttpEntity::queryStationTodayU(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string stationId = req.get_param_value("station_id");
    std::string catogray = req.get_param_value("category");
    njson jsondata;

    auto station = Application::data().getStation(Utils::toInt(stationId));
    if (station)
    {
        int n = Utils::timeDaySeconds() / 600;
        if (catogray == "1")
        {
            auto device = station->getDeviceByType(int(EDeviceType::BMS), "1");  // 使用 BMS 的数据
            if (device) {
                jsondata["U"] = VectorToJsonArray(device->cacheU, n);
                jsondata["I"] = VectorToJsonArray(device->cacheI, n);
                jsondata["P"] = VectorToJsonArray(device->cacheP, n);
            }
        }
        else if (catogray == "2")
        {
            auto device = station->getDeviceByType(int(EDeviceType::CHARGER), "1");
            if (device) {
                jsondata["U"] = VectorToJsonArray(device->cacheU, n);
                jsondata["I"] = VectorToJsonArray(device->cacheI, n);
                jsondata["P"] = VectorToJsonArray(device->cacheP, n);
            }
        }
        else if (catogray == "3")
        {
        }
    }
    json["data"] = jsondata;
    return Errcode::OK;
}

// 获取场站今日电流曲线数据，category: 1：储能，2：充电，3：光伏
Errcode HttpEntity::queryStationTodayI(const httplib::Request& req, njson& json, std::string& errmsg)
{
    return Errcode::OK;
}

// 获取场站今日功率曲线数据，category: 1：储能，2：充电，3：光伏
Errcode HttpEntity::queryStationTodayP(const httplib::Request& req, njson& json, std::string& errmsg)
{
    return Errcode::OK;
}

Errcode HttpEntity::queryDeviceList(const httplib::Request& req, njson& json, std::string& errmsg) 
{
    PageInfo pageinfo;
    pageinfo.index = Utils::toInt(req.get_param_value("page"));
    pageinfo.size = Utils::toInt(req.get_param_value("page_size"));
    string stationId = req.get_param_value("station_id");
    std::vector<Fields> result;
    auto err = DAO::queryDeviceListByStation(pageinfo, stationId, result);
    HttpHelper::setPagination(pageinfo, result, json);
    return err;
};

Errcode HttpEntity::insertDevice(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"station_id", "type", "name", "code", "model", "factory", "factory_tel", "is_open", "attrs"}, params);
    if (!params.contains("station_id")) { errmsg = "缺少参数[station_id]"; return Errcode::ERR_PARAM; }

    Errcode err = DAO::insertDevice(params);
    if (err == Errcode::OK)
    {
        int stationId = params.get<int>("station_id");
        auto station = Application::data().getStation(stationId);
        if (station) { station->addDevice(params); }
    }
    return err;
};

Errcode HttpEntity::updateDevice(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"device_id", "station_id", "type", "name", "code", "model", "factory", "factory_tel", "is_open", "attrs"}, params);

    Errcode err = DAO::updateDeviceById(params);
    if (err == Errcode::OK)
    {
        int stationId = params.get<int>("station_id");
        auto station = Application::data().getStation(stationId);
        if (station) { station->addDevice(params); }
    }
    return err;
};
Errcode HttpEntity::deleteDevice(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string primaryKey = DMDevice::DEVICE_ID;
    return DAO::remove(NULL, DMDevice::TABLENAME, primaryKey, req.get_param_value(primaryKey));
};
Errcode HttpEntity::queryDevicTypeDef(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string sql = "SELECT device_type_id, name FROM def_device_type;";
    std::vector<Fields> result;
    auto err = DAO::exec(NULL, sql, result);
    json["data"] = FieldsToJsonArray(result);
    return err;
}
Errcode HttpEntity::queryDevicByCategory(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"station_id", "category"}, params);
    if (!params.contains("station_id")) { errmsg = "缺少参数[station_id]"; return Errcode::ERR_PARAM; }
    if (!params.contains("category")) { errmsg = "缺少参数[category]"; return Errcode::ERR_PARAM; }

    int stationId = params.get<int>("station_id");
    int category = params.get<int>("category");
 
    njson jsondata = njson::array();
    auto station = Application::data().getStation(stationId);
    if (station)
    {
        std::vector<std::shared_ptr<Device>> vecDevice;
        station->getDeviceByCategory(category, vecDevice);

        for(auto& device: vecDevice)
        {
            if (device->isOpen)
            {
                njson jsonnode;
                jsonnode["stationId"] = stationId;
                jsonnode["category"] = category;
                jsonnode["device_id"] = device->deviceId;
                jsonnode["name"] = device->name;
                jsonnode["code"] = device->code;
                jsonnode["type"] = device->type;
                jsonnode["typename"] = Application::data().getDeviceNameById(device->type);
                jsonnode["view"] = 1;
                jsonnode["is_online"] = device->online;// ? "在线" : "离线";
                jsonnode["is_error"] = device->err;// ? "故障" : "正常";
                jsonnode["is_running"] = device->running;// ? "工作" : "空闲";
                {
                    VecPairSS vec;
                    device->getRuntimeParams(vec);
                    njson jsonarrayParams = njson::array();
                    for (auto& item: vec)
                    {
                        jsonarrayParams.push_back({{"k", item.first}, {"v", item.second}});
                    }
                    jsonnode["params"] = jsonarrayParams;
                }
                if (device->type == 106)
                {
                    VecPairSS vec;
                    device->getRuntimeParams1(vec);
                    njson jsonarrayParams = njson::array();
                    for (auto& item: vec)
                    {
                        jsonarrayParams.push_back({{"k", item.first}, {"v", item.second}});
                    }
                    jsonnode["params1"] = jsonarrayParams;
                }
                jsondata.push_back(jsonnode);
            }
        }
    }
    json["data"] = jsondata;

    njson jsongateway = njson::object();
    if (station)
    {
        jsongateway["msg"] = station->getGatewayParam();
        jsongateway["workmode"] = station->getGatewayMode();
        jsongateway["emu"] = station->emuStatus == 1 ? "在线" : (station->emuStatus == 0 ? "离线" : "--");
        jsongateway["cdz"] = station->cdzStatus == 1 ? "在线" : (station->cdzStatus == 0 ? "离线" : "--");
        jsongateway["soc_min"] = station->gatewayParam.socMin;
        jsongateway["soc_max"] = station->gatewayParam.socMax;
        jsongateway["capacity"] = station->gatewayParam.capacity;
        jsongateway["power_safe"] = station->gatewayParam.powerSafe;
        jsongateway["power_discharge"] = station->gatewayParam.powerDischarge;
        jsongateway["power_charge"] = station->gatewayParam.powerCharge;
        jsongateway["backflow"] = station->gatewayParam.backflow;
        jsongateway["overload"] = station->gatewayParam.overload;
    }
    json["gateway"] = jsongateway;
    return Errcode::OK;
}

Errcode HttpEntity::queryDevicCharts(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"station_id", "device_id"}, params);
    if (!params.contains("station_id")) { errmsg = "缺少参数[station_id]"; return Errcode::ERR_PARAM; }
    if (!params.contains("device_id")) { errmsg = "缺少参数[device_id]"; return Errcode::ERR_PARAM; }

    int stationId = params.get<int>("station_id");
    int deviceId = params.get<int>("device_id");
    auto device = Application::data().getDevice(stationId, deviceId);
   
    int npos = Utils::timeDaySeconds() / 600;
    std::vector<int> vecU(npos, 0);
    std::vector<int> vecI(npos, 0);
    std::vector<int> vecP(npos, 0);
    if (device)
    {
        for (size_t i = 0; i < npos; ++i)
        {
            if (i < device->cacheU.size()) vecU[i] = int(device->cacheU[i]);
            if (i < device->cacheI.size()) vecI[i] = int(device->cacheI[i]);
            if (i < device->cacheP.size()) vecP[i] = int(device->cacheP[i]);
        }
    }
    json["data"] = {{"V", vecU}, {"I", vecI}, {"P", vecP}};
    return Errcode::OK;
}

Errcode HttpEntity::queryDeviceBCUDetail(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"station_id", "device_id"}, params);
    if (!params.contains("station_id")) { errmsg = "缺少参数[station_id]"; return Errcode::ERR_PARAM; }
    if (!params.contains("device_id")) { errmsg = "缺少参数[device_id]"; return Errcode::ERR_PARAM; }
    
    int stationId = params.get<int>("station_id");
    int deviceId = params.get<int>("device_id");
    auto device = Application::data().getDevice(stationId, deviceId);

    njson jsondata = njson::array();
    if (device)
    {
        for (int i = 0; i<=device->bcuCount && i<device->vecBCUUnit.size(); ++i)
        {
            auto& row = device->vecBCUUnit[i];
            std::string soc = Utils::toStr(row[0], 1);
            std::string soh = Utils::toStr(row[1], 1);
            std::string u = Utils::toStr(row[2], 3);
            std::string t = Utils::toStr(row[3], 2);
            std::string r_i = Utils::toStr(row[4], 0);
            jsondata.push_back({{"SOC", soc}, {"SOH", soh}, {"V", u}, {"T", t}, {"R_i", r_i}});
        }
    }
    json["data"] = jsondata;
    return Errcode::OK;
}

Errcode HttpEntity::queryPolicyList(const httplib::Request& req, njson& json, std::string& errmsg) 
{ 
    PageInfo pageinfo;
    pageinfo.index = Utils::toInt(req.get_param_value("page"));
    pageinfo.size = Utils::toInt(req.get_param_value("page_size"));

    std::vector<Fields> result;
    auto err = DAO::queryPolicyList(pageinfo, result);
    HttpHelper::setPagination(pageinfo, result, json);
    return err;
};
Errcode HttpEntity::insertPolicy(const httplib::Request& req, njson& json, std::string& errmsg) 
{ 
    Fields params;
    GetRequestParams(req, {"type", "name", "describe", "value", "is_open"}, params);
    return DAO::insertPolicy(params);
};
Errcode HttpEntity::updatePolicy(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"policy_id", "type", "name", "describe", "value", "is_open"}, params);
    auto err = DAO::updatePolicyById(params);
    if (err == Errcode::OK)
    {
        int policyId = params.get<int>("policy_id");
        auto policy = Application::data().getPolicyById(policyId);
        if (policy)
        {
            policy->setFields(params);
        }
    }
    return err;
};
Errcode HttpEntity::deletePolicy(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"policy_id"}, params);
    return DAO::deletePolicyById(params.value("policy_id"));
};
Errcode HttpEntity::queryPolicyByType(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string type = req.get_param_value("type");
    std::string sql = "SELECT policy_id, `type`, name from policy WHERE `type`='" + type + "';";
    std::vector<Fields> result;
    int ret = DaoEntity::execOnce(sql, result);
    json["data"] = FieldsToJsonArray(result);
    return Errcode(ret);
}

Errcode HttpEntity::querySystemLogList(const httplib::Request& req, njson& json, std::string& errmsg)
{
    PageInfo pageinfo;
    pageinfo.index = Utils::toInt(req.get_param_value("page"));
    pageinfo.size = Utils::toInt(req.get_param_value("page_size"));

    std::vector<Fields> result;
    auto err = DAO::querySystemLogList(pageinfo, result);
    HttpHelper::setPagination(pageinfo, result, json);
    return err;
}

//Errcode insertSystemLog(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
Errcode HttpEntity::updateSystemLog(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"log_id", "status"}, params);
    return DAO::updateSystemLogById(params);
}

Errcode HttpEntity::queryAlertLogList(const httplib::Request& req, njson& json, std::string& errmsg)
{
    PageInfo pageinfo;
    pageinfo.index = Utils::toInt(req.get_param_value("page"));
    pageinfo.size = Utils::toInt(req.get_param_value("page_size"));

    std::vector<Fields> result;
    auto err = DAO::queryAlertLogList(pageinfo, result);
    HttpHelper::setPagination(pageinfo, result, json);
    return err;
}

//Errcode insertAlertLog(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
Errcode HttpEntity::updateAlertLog(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"log_id", "status"}, params);
    return DAO::updateAlertLogById(params);
}

Errcode HttpEntity::queryPredictionDetail(const httplib::Request& req, njson& json, std::string& errmsg)
{
    const int num = 144;
    std::vector<int> vecStoreIn(num, 0), vecStoreOut(num, 0), vecCharge(num, 0), vecSolar(num, 0), vecSolarP(num, 0);

    for (auto& item : Application::data().mapStation)
    {
        auto& station = item.second;
        //auto station = Application::data().getStation(5);
        for (int i = 0; i < num; ++i)
        {
            vecStoreIn[i] += station->predictStorageIn[i];
            vecStoreOut[i] += station->predictStorageOut[i];
            vecCharge[i] += station->predictCharge[i];
            vecSolar[i] = 0;
            vecSolarP[i] = 0;
        }
    }

    json["data"] = {
        {"W_store_in", vecStoreIn},
        {"W_store_out", vecStoreOut},
        {"W_charge", vecCharge},
        {"W_solar", vecSolar},
        {"P_solar", vecSolarP }
    };
    return Errcode::OK;
}

static void VerifyRequstParamsStatDate(Fields& params)
{
    if (!params.contains("end_date"))
    {
        if (!params.contains("start_date"))
        {
            params.set("end_date", Utils::dateStr());
            params.set("start_date", Utils::dateStr(Utils::date() - 86400 * 7));
        }
        else
        {
            params.set("end_date", Utils::dateStr(Utils::time(params.value("start_date") + " 00:00:00") + 86400 * 7));
        }
    }
}
static std::string VerifyStatSqlCondition(Fields& params)
{
    std::string stationId = params.value("station_id");
    std::string category = params.value("category");
    std::string dtStart = params.value("start_date");
    std::string dtEnd = params.value("end_date");

    std::string sqlCondition;
    if (!dtStart.empty() && dtEnd.empty())
    {
        sqlCondition += "dt BETWEEN '" + dtStart + "' AND '" + dtEnd + "'";
    }
    if (!stationId.empty())
    {
        if (!sqlCondition.empty()) sqlCondition += " AND ";
        sqlCondition += "ss.station_id='" + stationId + "'";
    }
    if (!category.empty() && category != "0")
    {
        //if (!sqlCondition.empty()) sqlCondition += " AND ";
        //sqlCondition += "ss.category='" + category  + "'";;
    }
    if (!sqlCondition.empty()) { sqlCondition = " WHERE " + sqlCondition; }
    return sqlCondition;
}
static std::string GetRequestStatParams(const httplib::Request& req, Fields& params)
{

    GetRequestParams(req, { "station_id", "category", "start_date", "end_date" }, params);
    VerifyRequstParamsStatDate(params);
    return VerifyStatSqlCondition(params);
}

static string GetStationStatusStr(int status)
{
    if (status == 1) return "空闲";
    else if (status == 2) return "充电";
    else if (status == 2) return "放电";
    else if (status == 9) return "故障";
    else return "离线";
}

Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    std::string sqlCondition = GetRequestStatParams(req, params);

    njson jsondata;
    std::string launchDate;
    float incomeTotal{};
    int storageDeviceNum = 0;
    int chargeDeviceNum = 0;
    int solarDeviceNum = 0;
    int capacityTotal{};

    bool isQueryStation = params.contains("station_id");
    if (isQueryStation)
    {
        std::string stationId = params.value("station_id");
        auto station = Application::data().getStation(Utils::toInt(stationId));
        if (station)
        {
            launchDate = station->launchDate;
            storageDeviceNum = 1; //: 储能设备数量
            chargeDeviceNum = station->getDeviceCount(2); //: 光伏设备数量
            solarDeviceNum = station->getDeviceCount(3); //: 光伏设备数量
            capacityTotal = station->capacity; // : 储能总容量（kWh），精度0.001
            jsondata["storage_status"] = GetStationStatusStr(station->storage.status);
            jsondata["charge_status"] = GetStationStatusStr(station->charge.status);
            jsondata["pv_status"] = "离线";
        }
    }
    else
    {
        auto& appdata = Application::data();
        launchDate = appdata.launchDate;   //: 系统上线启用日期，格式：yyyy-mm-dd
        for (auto& item : appdata.mapStation)
        {
            auto& station = item.second;
            storageDeviceNum += 1;
            chargeDeviceNum += station->getDeviceCount(2);
            solarDeviceNum += station->getDeviceCount(3);
            capacityTotal += station->capacity;
        }
    }
    
    jsondata["launch_date"] = launchDate; // 场站上线启用日期，格式：yyyy-mm-dd
    jsondata["storage_device_num"] = storageDeviceNum; //: 储能设备数量
    jsondata["charge_device_num"] = chargeDeviceNum; //: 储能设备数量
    jsondata["income_total"] = incomeTotal;     // : 累计收益（元），精度0.01
    jsondata["solar_device_num"] = solarDeviceNum; //: 光伏设备数量
    jsondata["capacity_total"] = capacityTotal; // : 储能总容量（kWh），精度0.001

    

    // 从 stat_total 表中查询日期最新的一条数据
    std::vector<Fields> result;
    std::string sql = std::format("SELECT st.* FROM stat_total st INNER JOIN "
        "(SELECT station_id, MAX(dt) max_dt FROM stat_total ss {} GROUP BY station_id) tmp "
        "ON st.station_id = tmp.station_id AND st.dt = tmp.max_dt; ", sqlCondition);
    DaoEntity::execOnce(sql, result);

    int eIn = 0;
    int eOut = 0;
    int tIn = 0;
    int tOut = 0;
    int nErr = 0;
    int eGen = 0;
    int eGrid = 0;
    int eCharge = 0;
    int income = 0;
    int incomeCharge = 0;
    for (int i=0; i<result.size(); ++i)
    {
        auto& fields = result[i];
        if (isQueryStation) 
        {
            if (params.value("station_id") == fields.value("station_id"))
            {
                eIn = fields.get<int>("E_in");
                eOut = fields.get<int>("E_out");
                tIn = fields.get<int>("t_in");
                tOut = fields.get<int>("t_out");
                eGen = fields.get<int>("E_gen");
                eGrid = fields.get<int>("E_grid");
                eCharge = fields.get<int>("E_charge"); 
                income = fields.get<int>("income");
            }
        }
        else 
        {
            eIn += fields.get<int>("E_in");
            eOut += fields.get<int>("E_out");
            tIn += fields.get<int>("t_in");
            tOut += fields.get<int>("t_out");
            eGen += fields.get<int>("E_gen");
            eGrid = fields.get<int>("E_grid");
            eCharge += fields.get<int>("E_charge");
            income += fields.get<int>("income");
        }
    }

    jsondata["storage_elect_in"] = eIn;    //储能充电电量（kWh），精度：0.001
    jsondata["storage_elect_out"] = eOut;  //储能放电电量（kWh），精度：0.001
    jsondata["storage_num_in"] = tIn; 	    //储能设备充电次数
    jsondata["storage_num_out"] = tOut; 	//储能设备放电次数
    //jsondata["storage_num_err"] = fields.value("n_err");  	//储能设备故障次数
    jsondata["solar_elect_gen"] = eGen;    //光伏发电电量（kWh），精度：0.001
    jsondata["solar_elect_grid"] = eGrid;    //光伏入网电量（kWh），精度：0.001
    //jsondata["solar_num_err"] = fields.value("n_err_solor");			//光伏设备故障次数
    jsondata["charge_elect"] = eCharge;	        //充电设备充电电量（kWh），精度：0.001
    //jsondata["charge_num"] = fields.value("n_charge");				//充电设备充电次数
    //jsondata["charge_num_err"] = fields.value("n_err_charge");		//充电设备故障次数
    jsondata["income_elect"] = income;		    //发电收益（元），精度：0.01
    //jsondata["income_charge"] = fields.value("income_charge");	        //充电收益（元），精度：0.01
    //jsondata["usage_rate"] = 0; //Utils::toStr(float(fields.get<int>("storage_usage") + fields.get<int>("storage_usage")) * 0.5f, 0);
    json["data"] = jsondata;

    return Errcode::OK;
}


Errcode HttpEntity::queryStatSystem(const httplib::Request& req, njson& json, std::string& errmsg)
{
    auto& appdata = Application::data();

    float income = 0.0;
    int nStation = 0;
    int nSolar {};
    int capacity {};
    int eGen {};
    int eGrid {};
    int eIn {};
    int eOut {};
    for (auto& item : appdata.mapStation)
    {
        auto& station = item.second;
        nStation += 1;
        nSolar += station->getDeviceCount(3);
        capacity += station->capacity;
        eGen += station->electGenTotal;
        eGrid += station->electGridTotal;
        eIn += station->statData.totalElectIn;
        eOut += station->statData.totalElectOut;
    }

    njson jsondata;
    jsondata["launch_date"] = appdata.launchDate; //: 系统上线启用日期，格式：yyyy-mm-dd
    jsondata["income_total"] = income; // : 累计收益（元），精度0.01
    jsondata["storage_device_num"] = nStation; //: 储能设备数量
    jsondata["solar_device_num"] = nSolar; //: 光伏设备数量
    jsondata["capacity_total"] = capacity; // : 储能总容量（kWh），精度0.001
    jsondata["solar_elect_gen"] = eGen; // : 发电总电量（kWh），精度0.001
    jsondata["solar_elect_grid"] = eGrid; // : 入网总电量（kWh），精度0.001
    jsondata["storage_elect_in"] = eIn; // : 储能充电总电量（kWh），精度0.001
    jsondata["storage_elect_out"] = eOut; // : 储能放电总电量（kWh），精度0.001

    // 总览页面：累计收益
    std::string sql = "SELECT st.* FROM stat_total st INNER JOIN "
        "(SELECT station_id, MAX(dt) max_dt FROM stat_total GROUP BY station_id) tmp "
        "ON st.station_id = tmp.station_id AND st.dt = tmp.max_dt; ";
    std::vector<Fields> result;
    DAO::exec(NULL, sql, result);
    for (auto& item: result)
    {
        income += item.get<float>("income");
    }
    jsondata["income_total"] = income;
    json["data"] = jsondata;
    return Errcode::OK;
}

Errcode HttpEntity::queryStatStationGroup(const httplib::Request& req, njson& json, std::string& errmsg)
{
    njson jsondata = njson::array();

    auto dao = DaoEntity::create("");
    std::string sql = R"(SELECT s.name station_name, st.* FROM stat_total st INNER JOIN
        (SELECT station_id, MAX(dt) max_dt FROM stat_total GROUP BY station_id) tmp
        ON st.station_id=tmp.station_id AND st.dt=tmp.max_dt
        LEFT JOIN station s ON s.station_id=st.station_id;)";
    std::vector<Fields> vecStations;
    auto err = dao->exec(sql, vecStations);
    for (auto& fields: vecStations)
    {
        njson jsonnode;
        jsonnode["station_name"] = fields.value("station_name");
        jsonnode["income"] = fields.get<float>("income");
        jsonnode["usage_rate"] = fields.get<float>("usage");
        jsondata.push_back(jsonnode);
    }
    json["data"] = jsondata;
    return Errcode(err);
}


Errcode HttpEntity::queryStatDayList(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"station_id", "category", "start_date", "end_date"}, params);
    std::string stationId = params.value("station_id");
    std::string category = params.value("category");
    std::string startDate = params.value("start_date");
    std::string endDate = params.value("end_date");
    if (endDate.empty())
    {
        int64_t t = Utils::time();
        endDate = Utils::dateStr(t);
        startDate = Utils::dateStr(t - 86400*7);
    }
    std::vector<Fields> result;
    auto err = DAO::queryStatStationGroup(NULL, stationId, category, startDate, endDate, result);

    if (!startDate.empty() && !endDate.empty())
    {
        std::map<std::string, Fields*> mapTemp;
        for (auto& item: result)
        {
            auto& dt = item.value("dt");
            mapTemp[dt] = &item;
        }

        int64_t t0 = Utils::time(startDate + " 00:00:00");
        int64_t t1 = Utils::time(endDate + " 00:00:00");
        int i = 0;

        njson jsondata = njson::array();
        for (int64_t t = t0; t<=t1; t += 86400)
        {
            i++;
            njson jsonrow;
            std::string dt = Utils::dateStr(t);
            Fields* fields = NULL;
            auto iter = mapTemp.find(dt);
            if (iter != mapTemp.end()) { fields = iter->second; }
            
            jsonrow["dt"] = dt.substr(5);
            jsonrow["storage_elect_in"]  = fields ? fields->value("storage_elect_in") : "0";
            jsonrow["storage_elect_out"] = fields ? fields->value("storage_elect_out") : "0";
            jsonrow["storage_num_in"]    = fields ? fields->value("storage_num_in") : "0";
            jsonrow["storage_num_out"]   = fields ? fields->value("storage_num_out") : "0";
            jsonrow["storage_num_err"]   = fields ? fields->value("storage_num_err") : "0";
            jsonrow["solar_elect_gen"]   = fields ? fields->value("solar_elect_gen") : "0";
            jsonrow["solar_elect_grid"]  = fields ? fields->value("solar_elect_grid") : "0";
            jsonrow["solar_num_err"]     = fields ? fields->value("solar_num_err") : "0";
            jsonrow["storage_usage"]     = fields ? fields->value("storage_usage") : "0";
            jsonrow["charge_elect"]      = fields ? fields->value("charge_elect") : "0";
            jsonrow["charge_num"]        = fields ? fields->value("charge_num") : "0";
            jsonrow["charge_num_err"]    = fields ? fields->value("charge_num_err") : "0";
            jsonrow["charge_usage"]      = fields ? fields->value("charge_usage") : "0";
            jsonrow["income_elect"]      = fields ? fields->value("income_elect") : "0";
            jsonrow["income_charge"]     = fields ? fields->value("income_charge") : "0";
            jsondata.push_back(jsonrow);
        }
        json["data"] = jsondata;
    }
    else
    {
        json["data"] = FieldsToJsonArray(result);
    }
    return err;
}

//Errcode HttpEntity::queryStatDayList(const httplib::Request& req, njson& json, std::string& errmsg)
//{
//    std::string sqlCondition = GetRequestStatParams(req);
//    std::string sql = R"(SELECT ss.*, d.name device_name, ddt.name device_type FROM stat_day ss 
//        LEFT JOIN device d ON d.device_id = ss.device_id 
//        LEFT JOIN def_device_type ddt  ON ddt.device_type_id = d.`type`)" + sqlCondition + ";";
//
//    std::vector<Fields> result;
//    int ret = DaoEntity::execOnce(sql, result);
//    json["data"] = FieldsToJsonArray(result);
//    return Errcode(ret);
//}

Errcode HttpEntity::queryStatDetailList(const httplib::Request& req, njson& json, std::string& errmsg)
{
    PageInfo pageinfo;
    pageinfo.index = Utils::toInt(req.get_param_value("page"));
    pageinfo.size = Utils::toInt(req.get_param_value("page_size"));

    Fields params;
    GetRequestParams(req, {"station_id", "category", "start_date", "end_date"}, params);

    std::vector<Fields> result;
    auto err = DAO::queryStatStationList(pageinfo, params, result);
    //json["data"] = FieldsToJsonArray(result);
    HttpHelper::setPagination(pageinfo, result, json);
    return err;
}

Errcode HttpEntity::queryStatCharts(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string dt = req.get_param_value("dt");
    std::string stationId = req.get_param_value("station_id");
    std::string category = req.get_param_value("category");

    if (stationId.empty()) { errmsg = "参数[station_id]错误"; return Errcode::ERR_PARAM; }
    if (category.empty()) { errmsg = "参数[category]错误"; return Errcode::ERR_PARAM; }

    if (dt.empty()) { dt=Utils::dateStr(); }

    njson jsondata;

    std::string sql = R"(SELECT hd.*, d.`type` device_type, d.code, ddt.category FROM history_day hd 
	    LEFT JOIN device d ON d.device_id = hd.device_id
	    LEFT JOIN def_device_type ddt ON d.`type` = ddt.device_type_id
	    WHERE dt=')" + dt + "' AND d.station_id='" + stationId + "' AND ddt.category='" + category + "';";

    std::vector<Fields> result;
    int ret = DaoEntity::execOnce(sql, result);
    if (ret != 0)
    {
        return Errcode(ret);
    }

    std::vector<double> vecV;
    std::vector<double>  vecI;
    std::vector<double>  vecP;
    for (auto fields : result)
    {
        int datetype = fields.get<int>("datatype"); // 1: 电压，2：电流，3：功率
        std::string val = fields.value("value");    // JSON 数组(double)
        int deviceType = fields.get<int>("device_type");
        int deviceCode = fields.get<int>("code");
        if (category == "1")
        {
            if (!(deviceType == int(EDeviceType::BMS)))  // 储能BMS（储能设备以BMS电池的数据作为总数据来展示）
            {
                continue;
            }
        }

        njson jsonval;
        if (JSON::parse(val, jsonval))
        {
            for (int i = 0; i<jsonval.size(); ++i)
            {
                double val = jsonval[i];
                if (datetype == 1)
                {
                    // 电压取最大
                    i >= vecV.size() ? vecV.push_back(val) : (val > vecV[i] ? (vecV[i] = val, (void)0) : (void)0);
                }
                else if (datetype == 2)
                {
                    // 电流取最大
                    i >= vecI.size() ? vecI.push_back(val) : (val > vecI[i] ? (vecI[i] = val, (void)0) : (void)0);
                }
                else if (datetype == 3)
                {
                    // 功率累加
                    i >= vecP.size() ? vecP.push_back(val) : (vecP[i] = vecP[i] + val, (void)0);
                }
            }
        }
    }
    json["data"] = {{"V", vecV}, {"I", vecI}, {"P", vecP}};
    return Errcode::OK;
}


Errcode HttpEntity::exportStatReport(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"station_id", "category", "start_date", "end_date"}, params);
    CheckRequiredParams(params, {"station_id", "category", "start_date", "end_date"}, errmsg);
    if (!errmsg.empty())
    {
        return Errcode::ERR_PARAM;
    }

    std::string stationId = params.value("station_id");
    std::string category = params.value("category");
    std::string startDate = params.value("start_date");
    std::string endDate = params.value("end_date");

    std::string sql = "SELECT s.name station_name, sd.* FROM stat_day sd LEFT JOIN station s ON sd.station_id=s.station_id";
    sql += " WHERE sd.station_id = '" + stationId + "' AND category = '" + category + "'";
    sql += " AND dt BETWEEN '" + startDate + "' AND '" + endDate + "2025-09-19' AND sd.category = '1'";

    std::string filename;
    std::vector<Fields> result;
    Errcode err = DAO::exec(NULL, sql, result);
    if (result.size() > 0)
    {
        filename = "export_" + Utils::timeStr(0, "%Y%m%d%H%M%S") + ".xlsx";
        XlsxEntity xlsx(Config::option.exportpath + "/" + filename);
        std::vector<std::pair<std::string, std::string>> headers;
        if (category == "1")
        {
            headers = {
                {"日期", "dt"}, {"场站", "station_name"}, {"类别", "category"},
                {"充电电量", "storage_elect_in"}, {"放电电量", "storage_elect_out"},
                {"充电次数", "storage_num_in"}, {"放电次数", "storage_num_out"},
                {"充电时长", "storage_t_in"}, {"放电时长", "storage_t_out"}
            };
        }
        else if (category == "2")
        {
            headers = {
                {"日期", "dt"}, {"场站", "station_name"}, {"类别", "category"},
                {"充电电量", "charge_elect"}, {"充电次数", "charge_num"}, {"充电时长", "charge_t"}
            };
        }
        else if (category == "3")
        {
            headers = {
                {"日期", "dt"}, {"场站", "station_name"}, {"类别", "category"},
                {"发电电量", "solar_elect_gen"}, {"入网电量", "solar_elect_grid"}, {"发电时长", "solar_t"},
            };
        }
        for (int row = 0; row<result.size(); ++row)
        {
            auto& fields = result[row];
            if (category == "1") { fields.value("category") = "储能设备"; }
            else if (category == "2") { fields.value("category") = "充电设备"; }
            else if (category == "3") { fields.value("category") = "发电设备"; }

            for (int col = 0; col<headers.size(); ++col)
            {
                if (row == 0)
                {
                    xlsx.setCell(row+1, col+1, headers[col].first);
                }
                xlsx.setCell(row+2, col+1, fields.value(headers[col].second));
            }
        }
        xlsx.close();
    }
    json["data"] = filename;
    return err;
}

Errcode HttpEntity::queryEnvironment(const httplib::Request& req, njson& json, std::string& errmsg)
{
    std::string stationId = req.get_param_value("station_id");
    auto& appdata = Application::data();

    auto station = appdata.getStation(Utils::toInt(stationId));
    if (!station)
    {
        spdlog::error("[http] request queryEnvironment failed, get station info error, station_id={}", stationId);
        return Errcode::ERR_PARAM;
    }
    
    njson jsondata;

    { // 温湿度
        auto& mapTempHumUnit = station->mapTempHumUnit;
        njson nodearray = njson::array();
        for (auto iter = mapTempHumUnit.begin(); iter!=mapTempHumUnit.end(); iter++)
        {
            auto& unit = iter->second;
            njson node;
            node["pos"] = "#" + std::to_string(iter->first);
            node["temp"] = Utils::toStr(unit.temp);
            node["hum"] = Utils::toStr(unit.hum);
            nodearray.push_back(node);
        }
        jsondata["temp_hum"] = nodearray;
    }
    { //空调
        auto& mapAircUnit = station->mapAircUnit;
        njson nodearray = njson::array();
        for (auto& item: mapAircUnit)
        {
            auto& unit = item.second;
            nodearray.push_back({{"pos", "开关"}, {"status", unit.powerOn == 0 ? "关机" : "开机"}});
            nodearray.push_back({{"pos", "启动制冷指令"}, {"status", unit.cooling == 0 ? "启动" : "关闭"}});
            nodearray.push_back({{"pos", "启动送风指令"}, {"status", unit.airSupply == 0 ? "关闭" : "启动"}});
            nodearray.push_back({{"pos", "启动待机指令"}, {"status", unit.standby == 0 ? "关闭" : "启动"}});
            nodearray.push_back({{"pos", "启动加热指令"}, {"status", unit.heating == 0 ? "关闭" : "启动"}});
            nodearray.push_back({{"pos", "传感器故障"}, {"status", unit.sensorAlarm == 0 ? "正常" : "告警"}});
            nodearray.push_back({{"pos", "高低电压告警"}, {"status", unit.voltageAlarm == 0 ? "正常" : "告警"}});
            nodearray.push_back({{"pos", "高低温告警"}, {"status", unit.tempAlarm == 0 ? "正常" : "告警"}});
            nodearray.push_back({{"pos", "高低压告警"}, {"status", unit.pressureAlarm == 0 ? "正常" : "告警"}});
            nodearray.push_back({{"pos", "压缩机告警"}, {"status", unit.compressorAlarm == 0 ? "正常" : "告警"}});
            nodearray.push_back({{"pos", "当前温度"}, {"status", std::to_string(unit.temp) + "℃"}});
            nodearray.push_back({{"pos", "当前湿度"}, {"status", std::to_string(unit.hum) + "%"}});
            break;
        }
        jsondata["airc"] = nodearray;
    }
    { // 消防
        static std::map<int, std::string> mapFireStatusDef = { {0, "正常"}, {1,"预警"}, {2,"火警"} };

        std::map<int, string> mapStatusDef = {{0, "无效"}, {1, "掉线"}, {2, "正常"}, {3, "启动"}};
        auto& mapFire40Unit = station->mapFire40Unit;
        njson nodearray = njson::array();
        for (auto iter = mapFire40Unit.begin(); iter!=mapFire40Unit.end(); ++iter)
        {
            auto& unit = iter->second;
            nodearray.push_back({{"pos", "主控状态"}, {"status", unit.statusMain == 0 ? "正常" : (unit.statusMain == 1 ? "预警" : "火警")}});
            nodearray.push_back({{"pos", "警铃是否使用"}, {"status", unit.usedAlarm == 0 ? "否" : "是"}});
            nodearray.push_back({{"pos", "警铃状态"}, {"status", mapStatusDef[unit.statusAlarm]}});  // 0：无效 1：掉线 2：正常 3：启动	
            nodearray.push_back({{"pos", "瓶头阀是否使用"}, {"status", unit.usedValve == 0 ? "否" : "是"}});
            nodearray.push_back({{"pos", "瓶头阀状态"}, {"status", mapStatusDef[unit.statusAlarm]}}); // 0：无效 1：掉线 2：正常 3：启动	
            nodearray.push_back({{"pos", "手报是否使用"}, {"status", unit.usedMCP == 0 ? "否" : "是"}});
            nodearray.push_back({{"pos", "手报状态"}, {"status", mapStatusDef[unit.statusAlarm]}});  // 0：无效 1：掉线 2：正常 3：启动	
            break;
        }
        jsondata["fire40"] = nodearray;
    }
    { // 冷机
        auto& mapCoolingUnit = station->mapCoolingUnit;
        njson nodearray = njson::array();
        for (auto& item: mapCoolingUnit)
        {
            auto& unit = item.second;
            njson node;
            nodearray.push_back({{"pos", "开关"}, {"status", unit.powerOn == 0 ? "关机" : "开机"}});
            nodearray.push_back({{"pos", "采样模式"}, {"status", unit.mode == 0 ? "出水温度" : "电芯温度"}});
            nodearray.push_back({{"pos", "制冷状态"}, {"status", unit.cooling == 0 ? "关闭" : "启动"}});
            nodearray.push_back({{"pos", "制热状态"}, {"status", unit.heating == 0 ? "关闭" : "启动"}});
            nodearray.push_back({{"pos", "高温告警"}, {"status", unit.highTemp == 0 ? "正常" : "告警"}});
            nodearray.push_back({{"pos", "低温告警"}, {"status", unit.lowTemp == 0 ? "正常" : "告警"}});
            nodearray.push_back({{"pos", "高压告警"}, {"status", unit.highPressure == 0 ? "正常" : "告警"}});
            nodearray.push_back({{"pos", "低压告警"}, {"status", unit.lowPressure == 0 ? "正常" : "告警"}});
        }
        jsondata["cooling"] = nodearray;
    }
    json["data"] = jsondata;
    return Errcode::OK;
}

Errcode HttpEntity::queryServiceApiList(const httplib::Request& req, njson& json, std::string& errmsg)
{
    PageInfo pageinfo;
    pageinfo.index = Utils::toInt(req.get_param_value("page"));
    pageinfo.size = Utils::toInt(req.get_param_value("page_size"));
    std::vector<Fields> result;
    std::string sql = "SELECT * FROM serviceapi;" ;
    auto err = DAO::exec(NULL, sql, result);
    HttpHelper::setPagination(pageinfo, result, json);
    return err;
}

Errcode HttpEntity::insertServiceApi(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"name", "describe", "params", "is_open"}, params);
    if (params.size() == 0) { return Errcode::ERR_PARAM; }

    return DAO::insert(NULL, "serviceapi", params);
}

Errcode HttpEntity::updateServiceApi(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"api_id", "name", "describe", "params", "is_open"}, params);
    if (params.size() == 0) { return Errcode::ERR_PARAM; }

    return  DAO::update(NULL, "serviceapi", params, "api_id");
}

Errcode HttpEntity::deleteServiceApi(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"api_id"}, params);
    return DAO::remove(NULL, "serviceapi", "api_id", params.value("api_id"));
}

Errcode HttpEntity::updateGatewayParams(const httplib::Request& req, njson& json, std::string& errmsg)
{
    //上下限SOC，安全输入功率，储能最大充放电功率，防逆流防过载回差。
    Fields params;
    GetRequestParams(req, {"station_id", "work_mode", "soc_min", "soc_max", "capacity", "power_safe", "power_discharge", "power_charge", "backflow", "overload"}, params);

    int stationId = params.get<int>("station_id");
    auto station = Application::data().getStation(stationId);

    if (params.contains("work_mode"))
    {
        int workMode = params.get<int>("work_mode");
        Fields fields;
        fields.set("station_id", params.value("station_id"));
        fields.set("work_mode", workMode);
        Errcode err = DAO::updateStationById(params);
    }

    if (station)
    {
        //params.get("work_mode", station->workMode);
        params.get("soc_min", station->gatewayParam.socMin);  // 储能放电下限值 SOC  40038  (%, 0-99)
        params.get("soc_max", station->gatewayParam.socMax);  // 储能充电上限值 SOC  40039  (%:1-100)
        params.get("capacity", station->gatewayParam.capacity); // 台区变压器容量  40040  (KVA 160-1600)
        params.get("power_safe", station->gatewayParam.powerSafe);   // 安全输入功率  40041  (KW 0-400)
        params.get("power_discharge", station->gatewayParam.powerDischarge);  // 储能最大放电功率  40042  (1KW 0-150)
        params.get("power_charge", station->gatewayParam.powerCharge);     // 储能最大充电功率  40043  (1KW 0-150)
        params.get("backflow", station->gatewayParam.backflow); // 防逆流回差  40058(1KW 10-300)
        params.get("overload", station->gatewayParam.overload); // 防过载回差  40059(1KW 10-300)

        station->setGarewayParams();
        return Errcode::OK;
    }
    return Errcode::ERR_PARAM;
}


static float SetPeriodRowJson(njson& jsonrow, std::string period, int eIn, int eOut, float priceIn, float priceOut, std::string dt)
{
    jsonrow["dt"] = dt;
    jsonrow["period"] = period;
    jsonrow["E_in"] = eIn;
    jsonrow["E_out"] = eOut;
    jsonrow["grid_price"] = Utils::toStr(priceIn);
    jsonrow["charge_price"] = Utils::toStr(priceOut);
    return eOut * priceOut - eIn * priceIn;
}

Errcode HttpEntity::queryEGridPeriod(const httplib::Request& req, njson& json, std::string& errmsg)
{
    Fields params;
    GetRequestParams(req, {"dt", "station_id"}, params);

    int stationId = params.get<int>("station_id");
    std::string dt = params.value("dt");
    //int year = 0;
    //int month = 0;
    //int day = 0;
    //int ret = sscanf(date.c_str(), "%d-%d-%d", &year, &month, &day);  // 解析3个值，成功返回3
    //if (ret != 3)
    //{
    //    return Errcode::ERR_PARAM;
    //}
    if (stationId == 0 || dt.empty())
    {
        return Errcode::ERR_PARAM;
    }

    float priceJ = 0.0;
    float priceF = 0.0;
    float priceP = 0.0;
    float priceG = 0.0;
    float priceC = 0.0;

    std::vector<Fields> result;
    auto err = DAO::exec(NULL, "select * from egrid_price;", result);
    if (err != Errcode::OK)
    {
        return err;
    }
    if (result.size() > 0)
    {
        for (auto& item: result)
        {
            int etype = item.get<int>("etype");
            float price = item.get<float>("price", 2);
            if (etype == 1) { priceJ = price; }
            else if (etype == 2) { priceF = price; }
            else if (etype == 3) { priceP = price; }
            else if (etype == 4) { priceG = price; }
            else if (etype == 9) { priceC = price; }
        }
    }

    //std::string sql = std::format("SELECT ep.*, ep2.price FROM egrid_period ep LEFT JOIN egrid_price ep2 ON ep.etype=ep2.etype  WHERE ep.`month`={};", month);
    std::string sql = std::format("select * from stat_total_day WHERE dt='{}' AND station_id='{}';", dt, stationId);
    err = DAO::exec(NULL, sql, result);
    if (err != Errcode::OK)
    {
        return err;
    }

    njson jsondata = njson::array();
    if (result.size() > 0)
    {
        auto& item = result[0];
        float incomeTotal = 0.0f;
        // 谷
        {
            njson jsonrow;
            float income = SetPeriodRowJson(jsonrow, "谷", item.get<int>("E_in_G"), item.get<int>("E_out_G"), priceG, priceC, dt);
            jsonrow["income"] = Utils::toStr(income);
            jsondata.push_back(jsonrow);
            incomeTotal += income;
        }
        // 平
        {
            njson jsonrow;
            float income = SetPeriodRowJson(jsonrow, "平", item.get<int>("E_in_P"), item.get<int>("E_out_P"), priceP, priceC, dt);
            jsonrow["income"] = Utils::toStr(income);
            jsondata.push_back(jsonrow);
            incomeTotal += income;
        }
        // 峰
        {
            njson jsonrow;
            float income = SetPeriodRowJson(jsonrow, "峰", item.get<int>("E_in_F"), item.get<int>("E_out_F"), priceF, priceC, dt);
            jsonrow["income"] = Utils::toStr(income);
            jsondata.push_back(jsonrow);
            incomeTotal += income;
        }
        // 尖
        {
            njson jsonrow;
            float income = SetPeriodRowJson(jsonrow, "尖", item.get<int>("E_in_J"), item.get<int>("E_out_J"), priceJ, priceC, dt);
            jsonrow["income"] = Utils::toStr(income);
            jsondata.push_back(jsonrow);
            incomeTotal += income;
        }
        // 总计
        {
            njson jsonrow;
            jsonrow["dt"] = dt;
            jsonrow["period"] = "总计";
            jsonrow["E_in"] = item.get<int>("E_in"); 
            jsonrow["E_out"] = item.get<int>("E_out");
            jsonrow["grid_price"] = "";
            jsonrow["charge_price"] = "";
            jsonrow["income"] = Utils::toStr(incomeTotal);
            jsondata.push_back(jsonrow);
        }
    }
    json["data"] = jsondata;
    return Errcode::OK;
}