#include "app.h"

#include "common/snowflake/snowflake.h"
#include "common/utils/process_util.h"
#include "common/utils/protobuf_util.h"
#include "common/utils/thread_pool.h"
#include "http/http_svr.h"
#include "mqtt/mqtt_cli.h"
#include "mqtt/mqtt_svr.h"
#include "wbs/wbs.h"

namespace zsy
{
    std::string App::HOME_DIR;
    std::string App::CONFIG_DIR;
    std::string App::JSON_CONFIG_FILE;
    std::string App::BIN_CONFIG_FILE;

    void App::run()
    {
        HOME_DIR = ProcessUtil::homeDir();
        CONFIG_DIR = HOME_DIR + "/config";
        JSON_CONFIG_FILE = CONFIG_DIR + "/config.json";
        BIN_CONFIG_FILE = CONFIG_DIR + "/config.bin";

        if (!loadConfig()) return;
        if (APP_CONFIG->daemon())
        {
            FreeConsole();
        }
        HttpSvr::init();
        MQTTSvr::init();
        MQTTCli::init();
        const auto mqtt_cli = MQTTCli::getRemoteCli();
        if (!mqtt_cli)
        {
            LOGGER_ERROR("未配置公网 MQTT 客户端");
            return;
        }
        auto appSn = APP_CONFIG->sn();
        mqtt_cli->subscribe(appSn + "/stop", [](const MQTTMsg &msg)
        {
            LOGGER_INFO("收到停止指令，正在退出应用");
            Q_EMIT APP->stopApp();
            qApp->exit();
        });

        mqtt_cli->subscribe(appSn + "/restart", [](const MQTTMsg &msg)
        {
            LOGGER_INFO("收到重启指令，准备重启应用");
            Q_EMIT APP->stopApp();
            std::this_thread::sleep_for(std::chrono::milliseconds(10000));
            Q_EMIT APP->startApp();
        });

        mqtt_cli->subscribe(appSn + "/reset", [](const MQTTMsg &msg)
        {
            LOGGER_INFO("收到重置指令，准备重置应用");
            Q_EMIT APP->resetApp();
        });
        Wbs::init();
    }

    void App::stop()
    {
        Wbs::destroy();
        MQTTCli::destroy();
        HttpSvr::destroy();
        MQTTSvr::destroy();
    }

    void App::restart()
    {
        ThreadPool::submit([]
        {
            stop();
            run();
        });
    }

    App::App(QObject *parent)
        : QObject(parent)
    {
        connect(this, &App::startApp, this, &App::onStartApp);
        connect(this, &App::stopApp, this, &App::onStopApp);
        connect(this, &App::restartApp, this, &App::onRestartApp);
        connect(this, &App::resetApp, this, &App::onResetApp);
    }

    void App::onStartApp()
    {
        run();
    }

    void App::onStopApp()
    {
        stop();
    }

    void App::onRestartApp()
    {
        stop();
        run();
    }

    void App::onResetApp()
    {
    }

    void App::reset(const std::string &configStr)
    {
        if (!configStr.empty())
        {
            const auto reset_config = PbUtil::fromJsonStr<AppConfig>(configStr);
            if (!reset_config)
            {
                LOGGER_ERROR("重置配置文件格式错误 {}", configStr);
                return;
            }
            APP_CONFIG = std::make_shared<AppConfig>(reset_config.value());
            saveConfig();
            LOGGER_INFO("已保存配置");
        } else
        {
            LOGGER_INFO("无要修改的配置");
            return;
        }
        LOGGER_INFO("准备重启应用：{}", configStr);
        restart();
    }

    std::string App::sn()
    {
        return APP_CONFIG->sn();
    }

    std::string App::stationSn()
    {
        return APP_CONFIG->station_sn();
    }

    std::string App::name()
    {
        return APP_CONFIG->name();
    }

    bool App::loadConfig()
    {
        if (const auto app_config = PbUtil::readBin<AppConfig>(BIN_CONFIG_FILE); app_config)
        {
            APP_CONFIG = std::make_shared<AppConfig>(app_config.value());
            LOGGER_INFO("已加载配置文件：{}", BIN_CONFIG_FILE);
            return true;
        }

        if (const auto app_config = PbUtil::readJson<AppConfig>(JSON_CONFIG_FILE); app_config)
        {
            APP_CONFIG = std::make_shared<AppConfig>(app_config.value());
            LOGGER_INFO("已加载配置文件：{}", JSON_CONFIG_FILE);
            return true;
        }

        LOGGER_WARN("未找到配置文件，将使用默认配置");

        APP_CONFIG = std::make_shared<AppConfig>(defaultConfig());
        return saveConfig();
    }

    bool App::saveConfig()
    {
        FileUtil::createDir(CONFIG_DIR);
        if (PbUtil::writeBin(BIN_CONFIG_FILE, *APP_CONFIG))
        {
            LOGGER_INFO("配置已保存到二进制文件：{}", BIN_CONFIG_FILE);
            return true;
        } else
        {
            LOGGER_ERROR("保存配置到二进制文件失败：{}", BIN_CONFIG_FILE);
            return false;
        }
    }

    const AppConfig &App::defaultConfig()
    {
        static AppConfig default_config = []
        {
            AppConfig config_;
            auto appSn = Snowflake::genIdStr();
            config_.set_sn(appSn);
            config_.set_name("未初始化设备");

            const auto http_config = config_.mutable_http_config();
            const auto http_config_svr = http_config->mutable_svr();
            http_config_svr->set_name("HTTP 服务器");
            http_config_svr->set_sn("HTTP_SVR");
            http_config_svr->set_port(8080);

            const auto mqtt_config = config_.mutable_mqtt_config();
            const auto mqtt_svr = mqtt_config->mutable_svr();
            mqtt_svr->set_name("MQTT 服务器");
            mqtt_svr->set_sn("MQTT_SVR");
            mqtt_svr->set_port(1883);

            const auto mqtt_cli1 = mqtt_config->add_clis();
            mqtt_cli1->set_sn("0");
            mqtt_cli1->set_name("公网 MQTT 客户端");
            mqtt_cli1->set_ip("localhost");
            mqtt_cli1->set_port(1883);
            mqtt_cli1->set_client_id("remote_" + appSn);
            mqtt_cli1->set_username("none");
            mqtt_cli1->set_passwd("none");
            const auto mqtt_cli2 = mqtt_config->add_clis();
            mqtt_cli2->set_sn("1");
            mqtt_cli2->set_name("内网 MQTT 客户端");
            mqtt_cli2->set_ip("localhost");
            mqtt_cli2->set_port(1883);
            mqtt_cli2->set_client_id("local_" + appSn);
            mqtt_cli2->set_username("none");
            mqtt_cli2->set_passwd("none");
            return config_;
        }();
        return default_config;
    }

} // zsy
