
/*
 * Copyright (c) KylinSoft  Co., Ltd. 2024. All rights reserved.
 *
 * kaiming is licensed under the GPL v2.0+.
 * 
 * See the LICENSE file for more details.
 */

 #include <set>
 #include <unordered_set>
#include "KMRemoteModify.h"
#include "common/KMError.h"
#include "common/KMLogger.h"
#include "common/kmtranslation.h"

 using namespace std;
 
class KMRemoteModify::Options : public KMOption::Options
{
public:
    Options() = default;
    ~Options() override = default;

    void checkUnknownOptions(int argc, char** argv);

protected:
    /**
     * @brief 命令行参数解析后操作
     */
    void preParseHook() override;

    /**
     * @brief 命令行参数解析后操作
     */
    void postParseHook() override;

private:
    /**
     * @brief 命令行参数添加描述选项
     */
    void addOptions();

public:
    bool m_bHelp;
    std::string m_remoteName;
    std::string m_newUrl;
    
    std::string args;
};

void KMRemoteModify::Options::preParseHook()
{
    addOptions();
}

/**
 * @brief 命令行参数解析后操作
 */
void KMRemoteModify::Options::postParseHook()
{
    if (m_bHelp)
    {
        showUsage();
        exit(EXIT_SUCCESS);
    }
}

/**
 * @brief 命令行参数添加描述选项
 */
void KMRemoteModify::Options::addOptions()
{
    setDescription(_("\nUsage:\n \tkaiming remote-modify REPONAME --repo=URL\n"));
    //CHANGE帮助选项
    addOption("help","h", KMOption::value<bool>(&m_bHelp)->defaultValue(false), _("display Help Options"));   

    //位置选项
    addPositionOption("REPONAME", KMOption::value<std::string>(&m_remoteName), 1, _("Remote repo name"));
    addPositionOption("--repo", KMOption::value<std::string>(&m_newUrl), 1, _("Remote repo url"));
}

class KMRemoteModify::Private
{
public:
    std::shared_ptr<Options> m_options;
    std::shared_ptr<KMEnv> m_env;
};

REGISTER_SUBCOMMAND_DYNCREATE(remote-modify, KMRemoteModify)

KMRemoteModify::KMRemoteModify()
    : d(std::make_unique<Private>())
{
    d->m_options = std::make_shared<Options>();
    d->m_env = shared_ptr<KMEnv>(new KMEnv());
}

KMRemoteModify::~KMRemoteModify() = default;

int KMRemoteModify::dispose(int argc, char **argv) 
{
    d->m_options->checkUnknownOptions(argc, argv);
    d->m_options->parseCommandLine(argc, argv);

     // 环境校验
     if (!d->m_env->passEnvCheck())
     {
         kmlogger.error("Failed to check environments!");
         return KM_ERROR_CHECK_ENV_FAILED;
     }
 
    // 检查参数数量
    if (argc != 3) {
        std::cout << "invaild args" << std::endl;
        return KM_ERROR_INVALID_ARGS;
    }

    std::string remoteName = argv[1];
    std::string url = argv[2];

    // 验证参数格式：第二个参数必须是 url= 开头
    if (url.find("--repo=") != 0) {
        std::cout << "Invaild args" << std::endl;
        return KM_ERROR_INVALID_ARGS;
    }
    else
    {
        url = url.substr(7);
    }

    // 读取配置文件
    std::ifstream inFile("/opt/kaiming/repo/config");
    if (!inFile) {
        std::cout << "Not find config file" << std::endl;
        return KM_ERROR_CONFIG_NOT_FOUND;
    }

    std::vector<std::string> lines;
    std::string line;
    bool inTargetSection = false;
    bool modified = false;

    while (std::getline(inFile, line)) {
        // 检查是否进入目标 remote section（动态匹配 remoteName）
        if (line.find("[remote \"" + remoteName + "\"]") != std::string::npos) {
            inTargetSection = true;
            lines.push_back(line);
            continue;
        }

        // 如果在目标 section 且找到 url 行，则修改
        if (inTargetSection && line.find("url=") == 0) {
            line ="url=" + url; // 替换为新的 URL
            modified = true;
            inTargetSection = false; // 修改后退出 section
        } else if (line.find("[") == 0) {
            // 遇到新的 section 头，退出当前 section
            inTargetSection = false;
        }

        lines.push_back(line);
    }
    inFile.close();

    // 如果有修改，写回文件
    if (modified) {
        std::ofstream outFile("/opt/kaiming/repo/config");
        if (!outFile) {
            return KM_ERROR_CONFIG_WRITE_FAILED;
        }
        for (const auto& l : lines) {
            outFile << l << "\n";
        }
        outFile.close();
        std::cout << "modify url successed" << std::endl;
    }

    return KM_ERROR_NO;
}

void KMRemoteModify::Options::checkUnknownOptions(int argc, char** argv)
{
    std::unordered_set<std::string> validOptions = {
        "--help", "-h",
        "--repo",
        "--loglevel",
        "--verbose", "-v",
    };

    for (int i = 1; i < argc; ++i) 
    {
        std::string arg(argv[i]);

        if (arg.size() >= 1 && arg[0] == '-') 
        {
            std::string opt = arg;
            auto eq_pos = opt.find('=');
            if (eq_pos != std::string::npos)
            {
                opt = opt.substr(0, eq_pos);
            }

            if (validOptions.find(opt) == validOptions.end()) 
            {
                KMError(_("Unrecognized option “") + arg + "”");
                std::cerr << _("Please use ") << ("'kaiming remote-modify --help'") << _(" to see available options.") << std::endl;
                exit(EXIT_FAILURE);
            }
        }
    }
}