// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "agent/utils.h"

// IWYU pragma: no_include <bthread/errno.h>
#include <errno.h> // IWYU pragma: keep
#include <fmt/format.h>
#include <gen_cpp/FrontendService.h>
#include <gen_cpp/HeartbeatService_types.h>
#include <gen_cpp/Types_types.h>
#include <glog/logging.h>
#include <rapidjson/document.h>
#include <rapidjson/encodings.h>
#include <rapidjson/rapidjson.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <thrift/transport/TTransportException.h>

#include <cstdio>
#include <exception>
#include <fstream>
#include <memory>
#include <utility>

#include "common/config.h"
#include "common/status.h"
#include "runtime/cluster_info.h"
#include "util/client_cache.h"

namespace doris {
class TConfirmUnusedRemoteFilesRequest;
class TConfirmUnusedRemoteFilesResult;
class TFinishTaskRequest;
class TMasterResult;
class TReportRequest;
} // namespace doris

using apache::thrift::transport::TTransportException;

namespace doris {

static std::unique_ptr<MasterServerClient> s_client;

MasterServerClient* MasterServerClient::create(const ClusterInfo* cluster_info) {
    s_client.reset(new MasterServerClient(cluster_info));
    return s_client.get();
}

MasterServerClient* MasterServerClient::instance() {
    return s_client.get();
}

MasterServerClient::MasterServerClient(const ClusterInfo* cluster_info)
        : _cluster_info(cluster_info),
          _client_cache(std::make_unique<FrontendServiceClientCache>(
                  config::max_master_fe_client_cache_size)) {
    _client_cache->init_metrics("master_fe");
}

Status MasterServerClient::finish_task(const TFinishTaskRequest& request, TMasterResult* result) {
    Status client_status;
    FrontendServiceConnection client(_client_cache.get(), _cluster_info->master_fe_addr,
                                     config::thrift_rpc_timeout_ms, &client_status);

    if (!client_status.ok()) {
        LOG(WARNING) << "fail to get master client from cache. "
                     << "host=" << _cluster_info->master_fe_addr.hostname
                     << ", port=" << _cluster_info->master_fe_addr.port
                     << ", code=" << client_status.code();
        return Status::InternalError("Failed to get master client");
    }

    try {
        try {
            client->finishTask(*result, request);
        } catch (TTransportException& e) {
            LOG(WARNING) << "master client, retry finishTask: " << e.what();
            client_status = client.reopen(config::thrift_rpc_timeout_ms);
            if (!client_status.ok()) {
                LOG(WARNING) << "fail to get master client from cache. "
                             << "host=" << _cluster_info->master_fe_addr.hostname
                             << ", port=" << _cluster_info->master_fe_addr.port
                             << ", code=" << client_status.code();
                return Status::RpcError("Master client finish task failed");
            }
            client->finishTask(*result, request);
        }
    } catch (std::exception& e) {
        RETURN_IF_ERROR(client.reopen(config::thrift_rpc_timeout_ms));
        LOG(WARNING) << "fail to finish_task. "
                     << "host=" << _cluster_info->master_fe_addr.hostname
                     << ", port=" << _cluster_info->master_fe_addr.port << ", error=" << e.what();
        return Status::InternalError("Fail to finish task");
    }

    return Status::OK();
}

Status MasterServerClient::report(const TReportRequest& request, TMasterResult* result) {
    Status client_status;
    FrontendServiceConnection client(_client_cache.get(), _cluster_info->master_fe_addr,
                                     config::thrift_rpc_timeout_ms, &client_status);

    if (!client_status.ok()) {
        LOG(WARNING) << "fail to get master client from cache. "
                     << "host=" << _cluster_info->master_fe_addr.hostname
                     << ", port=" << _cluster_info->master_fe_addr.port
                     << ", code=" << client_status;
        return Status::InternalError("Fail to get master client from cache");
    }

    try {
        try {
            client->report(*result, request);
        } catch (TTransportException& e) {
            TTransportException::TTransportExceptionType type = e.getType();
            if (type != TTransportException::TTransportExceptionType::TIMED_OUT) {
                // if not TIMED_OUT, retry
                LOG(WARNING) << "master client, retry finishTask: " << e.what();

                client_status = client.reopen(config::thrift_rpc_timeout_ms);
                if (!client_status.ok()) {
                    LOG(WARNING) << "fail to get master client from cache. "
                                 << "host=" << _cluster_info->master_fe_addr.hostname
                                 << ", port=" << _cluster_info->master_fe_addr.port
                                 << ", code=" << client_status.code();
                    return Status::InternalError("Fail to get master client from cache");
                }

                client->report(*result, request);
            } else {
                // TIMED_OUT exception. do not retry
                // actually we don't care what FE returns.
                LOG(WARNING) << "fail to report to master: " << e.what();
                return Status::InternalError("Fail to report to master");
            }
        }
    } catch (std::exception& e) {
        RETURN_IF_ERROR(client.reopen(config::thrift_rpc_timeout_ms));
        LOG(WARNING) << "fail to report to master. "
                     << "host=" << _cluster_info->master_fe_addr.hostname
                     << ", port=" << _cluster_info->master_fe_addr.port
                     << ", code=" << client_status.code() << ", reason=" << e.what();
        return Status::InternalError("Fail to report to master");
    }

    return Status::OK();
}

Status MasterServerClient::confirm_unused_remote_files(
        const TConfirmUnusedRemoteFilesRequest& request, TConfirmUnusedRemoteFilesResult* result) {
    Status client_status;
    FrontendServiceConnection client(_client_cache.get(), _cluster_info->master_fe_addr,
                                     config::thrift_rpc_timeout_ms, &client_status);

    if (!client_status.ok()) {
        return Status::InternalError(
                "fail to get master client from cache. host={}, port={}, code={}",
                _cluster_info->master_fe_addr.hostname, _cluster_info->master_fe_addr.port,
                client_status.code());
    }
    try {
        try {
            client->confirmUnusedRemoteFiles(*result, request);
        } catch (TTransportException& e) {
            TTransportException::TTransportExceptionType type = e.getType();
            if (type != TTransportException::TTransportExceptionType::TIMED_OUT) {
                // if not TIMED_OUT, retry
                LOG(WARNING) << "master client, retry finishTask: " << e.what();

                client_status = client.reopen(config::thrift_rpc_timeout_ms);
                if (!client_status.ok()) {
                    return Status::InternalError(
                            "fail to get master client from cache. host={}, port={}, code={}",
                            _cluster_info->master_fe_addr.hostname,
                            _cluster_info->master_fe_addr.port, client_status.code());
                }

                client->confirmUnusedRemoteFiles(*result, request);
            } else {
                // TIMED_OUT exception. do not retry
                // actually we don't care what FE returns.
                return Status::InternalError(
                        "fail to confirm unused remote files. host={}, port={}, code={}, reason={}",
                        _cluster_info->master_fe_addr.hostname, _cluster_info->master_fe_addr.port,
                        client_status.code(), e.what());
            }
        }
    } catch (std::exception& e) {
        RETURN_IF_ERROR(client.reopen(config::thrift_rpc_timeout_ms));
        return Status::InternalError(
                "fail to confirm unused remote files. host={}, port={}, code={}, reason={}",
                _cluster_info->master_fe_addr.hostname, _cluster_info->master_fe_addr.port,
                client_status.code(), e.what());
    }

    return Status::OK();
}

bool AgentUtils::exec_cmd(const std::string& command, std::string* errmsg, bool redirect_stderr) {
    // The exit status of the command.
    uint32_t rc = 0;

    // Redirect stderr to stdout to get error message.
    std::string cmd = command;
    if (redirect_stderr) {
        cmd += " 2>&1";
    }

    // Execute command.
    FILE* fp = popen(cmd.c_str(), "r");
    if (fp == nullptr) {
        *errmsg = fmt::format("popen failed. {}, with errno: {}.\n", strerror(errno), errno);
        return false;
    }

    // Get command output.
    char result[1024] = {'\0'};
    while (fgets(result, sizeof(result), fp) != nullptr) {
        *errmsg += result;
    }

    // Waits for the associated process to terminate and returns.
    rc = pclose(fp);
    if (rc == -1) {
        if (errno == ECHILD) {
            *errmsg += "pclose cannot obtain the child status.\n";
        } else {
            *errmsg += fmt::format("Close popen failed. {}, with errno: {}.\n", strerror(errno),
                                   errno);
        }
        return false;
    }

    // Get return code of command.
    int32_t status_child = WEXITSTATUS(rc);
    if (status_child == 0) {
        return true;
    } else {
        return false;
    }
}

bool AgentUtils::write_json_to_file(const std::map<std::string, std::string>& info,
                                    const std::string& path) {
    rapidjson::Document json_info(rapidjson::kObjectType);
    for (auto& it : info) {
        json_info.AddMember(rapidjson::Value(it.first.c_str(), json_info.GetAllocator()).Move(),
                            rapidjson::Value(it.second.c_str(), json_info.GetAllocator()).Move(),
                            json_info.GetAllocator());
    }
    rapidjson::StringBuffer json_info_str;
    rapidjson::Writer<rapidjson::StringBuffer> writer(json_info_str);
    json_info.Accept(writer);
    std::ofstream fp(path);
    if (!fp) {
        return false;
    }
    fp << json_info_str.GetString() << std::endl;
    fp.close();

    return true;
}

} // namespace doris
