// 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 "http/utils.h"

#include <absl/strings/str_split.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/stat.h>
#include <unistd.h>

#include <ostream>
#include <string>
#include <unordered_map>
#include <vector>

#include "common/config.h"
#include "common/logging.h"
#include "common/status.h"
#include "common/utils.h"
#include "http/http_channel.h"
#include "http/http_client.h"
#include "http/http_common.h"
#include "http/http_headers.h"
#include "http/http_method.h"
#include "http/http_request.h"
#include "http/http_status.h"
#include "io/fs/file_system.h"
#include "io/fs/local_file_system.h"
#include "olap/wal/wal_manager.h"
#include "runtime/exec_env.h"
#include "util/md5.h"
#include "util/path_util.h"
#include "util/security.h"
#include "util/url_coding.h"

namespace doris {

const uint32_t CHECK_SUPPORT_TIMEOUT = 3;
const uint32_t DOWNLOAD_FILE_MAX_RETRY = 3;
const uint32_t LIST_REMOTE_FILE_TIMEOUT = 15;

std::string encode_basic_auth(const std::string& user, const std::string& passwd) {
    std::string auth = user + ":" + passwd;
    std::string encoded_auth;
    base64_encode(auth, &encoded_auth);
    static std::string s_prefix = "Basic ";
    return s_prefix + encoded_auth;
}

bool parse_basic_auth(const HttpRequest& req, std::string* user, std::string* passwd) {
    // const auto& token = req.header(HttpHeaders::AUTH_TOKEN);

    const char k_basic[] = "Basic ";
    const auto& auth = req.header(HttpHeaders::AUTHORIZATION);
    if (auth.compare(0, sizeof(k_basic) - 1, k_basic, sizeof(k_basic) - 1) != 0) {
        return false;
    }
    std::string encoded_str = auth.substr(sizeof(k_basic) - 1);
    std::string decoded_auth;
    if (!base64_decode(encoded_str, &decoded_auth)) {
        return false;
    }
    auto pos = decoded_auth.find(':');
    if (pos == std::string::npos) {
        return false;
    }
    user->assign(decoded_auth.c_str(), pos);
    passwd->assign(decoded_auth.c_str() + pos + 1);

    return true;
}

bool parse_basic_auth(const HttpRequest& req, AuthInfo* auth) {
    // deprecated, removed in 3.1, use AUTH_TOKEN
    const auto& token = req.header("token");
    // deprecated, removed in 3.1, use AUTH_TOKEN
    const auto& auth_code = req.header(HTTP_AUTH_CODE);
    const auto& auth_token = req.header(HttpHeaders::AUTH_TOKEN);

    std::tuple<std::string, std::string, std::string> tmp;
    auto& [user, pass, cluster] = tmp;
    bool valid_basic_auth = parse_basic_auth(req, &user, &pass);
    if (valid_basic_auth) { // always set the basic auth, the user may be useful
        auto pos = user.find('@');
        if (pos != std::string::npos) {
            cluster.assign(user.c_str() + pos + 1);
            user.assign(user.c_str(), pos); // user is updated
        }
        auth->user = user;
        auth->passwd = pass;
        auth->cluster = cluster;
    }

    if (!token.empty()) {
        auth->token = token; // deprecated
    } else if (!auth_token.empty()) {
        auth->token = auth_token;
    } else if (!auth_code.empty()) {
        auth->auth_code = std::stoll(auth_code); // deprecated
    } else if (!valid_basic_auth) {
        return false;
    }

    // set user ip
    auth->user_ip.assign(req.remote_host() != nullptr ? req.remote_host() : "");

    return true;
}

// Do a simple decision, only deal a few type
std::string get_content_type(const std::string& file_name) {
    std::string file_ext = path_util::file_extension(file_name);
    VLOG_TRACE << "file_name: " << file_name << "; file extension: [" << file_ext << "]";
    if (file_ext == std::string(".html") || file_ext == std::string(".htm")) {
        return "text/html; charset=utf-8";
    } else if (file_ext == std::string(".js")) {
        return "application/javascript; charset=utf-8";
    } else if (file_ext == std::string(".css")) {
        return "text/css; charset=utf-8";
    } else if (file_ext == std::string(".txt")) {
        return "text/plain; charset=utf-8";
    } else if (file_ext == std::string(".png")) {
        return "image/png";
    } else if (file_ext == std::string(".ico")) {
        return "image/x-icon";
    } else {
        return "text/plain; charset=utf-8";
    }
}

void do_file_response(const std::string& file_path, HttpRequest* req,
                      bufferevent_rate_limit_group* rate_limit_group, bool is_acquire_md5) {
    if (file_path.find("..") != std::string::npos) {
        LOG(WARNING) << "Not allowed to read relative path: " << file_path;
        HttpChannel::send_error(req, HttpStatus::FORBIDDEN);
        return;
    }

    // read file content and send response
    int fd = open(file_path.c_str(), O_RDONLY);
    if (fd < 0) {
        LOG(WARNING) << "Failed to open file: " << file_path;
        HttpChannel::send_error(req, HttpStatus::NOT_FOUND);
        return;
    }
    struct stat st;
    auto res = fstat(fd, &st);
    if (res < 0) {
        close(fd);
        LOG(WARNING) << "Failed to open file: " << file_path;
        HttpChannel::send_error(req, HttpStatus::NOT_FOUND);
        return;
    }

    int64_t file_size = st.st_size;

    // TODO(lingbin): process "IF_MODIFIED_SINCE" header
    // TODO(lingbin): process "RANGE" header
    const std::string& range_header = req->header(HttpHeaders::RANGE);
    if (!range_header.empty()) {
        // analyse range header
    }

    req->add_output_header(HttpHeaders::CONTENT_TYPE, get_content_type(file_path).c_str());

    if (is_acquire_md5) {
        Md5Digest md5;

        void* buf = mmap(nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0);
        md5.update(buf, file_size);
        md5.digest();
        munmap(buf, file_size);

        req->add_output_header(HttpHeaders::CONTENT_MD5, md5.hex().c_str());
    }

    if (req->method() == HttpMethod::HEAD) {
        close(fd);
        req->add_output_header(HttpHeaders::CONTENT_LENGTH, std::to_string(file_size).c_str());
        HttpChannel::send_reply(req);
        return;
    }

    HttpChannel::send_file(req, fd, 0, file_size, rate_limit_group);
}

void do_dir_response(const std::string& dir_path, HttpRequest* req, bool is_acquire_filesize) {
    bool exists = true;
    std::vector<io::FileInfo> files;
    Status st = io::global_local_filesystem()->list(dir_path, true, &files, &exists);
    if (!st.ok()) {
        LOG(WARNING) << "Failed to scan dir. " << st;
        HttpChannel::send_error(req, HttpStatus::INTERNAL_SERVER_ERROR);
        return;
    }

    VLOG_DEBUG << "list dir: " << dir_path << ", exists: " << exists
               << ", file count: " << files.size();

    if (!exists) {
        HttpChannel::send_error(req, HttpStatus::NOT_FOUND);
        return;
    }

    const std::string FILE_DELIMITER_IN_DIR_RESPONSE = "\n";

    std::stringstream result;
    for (auto& file : files) {
        result << file.file_name << FILE_DELIMITER_IN_DIR_RESPONSE;
        if (is_acquire_filesize) {
            result << file.file_size << FILE_DELIMITER_IN_DIR_RESPONSE;
        }
    }

    std::string result_str = result.str();
    HttpChannel::send_reply(req, result_str);
}

bool load_size_smaller_than_wal_limit(int64_t content_length) {
    // 1. req->header(HttpHeaders::CONTENT_LENGTH) will return streamload content length. If it is empty or equals to 0, it means this streamload
    // is a chunked streamload and we are not sure its size.
    // 2. if streamload content length is too large, like larger than 80% of the WAL constrain.
    //
    // This two cases, we are not certain that the Write-Ahead Logging (WAL) constraints allow for writing down
    // these blocks within the limited space. So we need to set group_commit = false to avoid dead lock.
    size_t max_available_size = ExecEnv::GetInstance()->wal_mgr()->get_max_available_size();
    return (content_length < 0.8 * max_available_size);
}

Status is_support_batch_download(const std::string& endpoint) {
    std::string url = fmt::format("http://{}/api/_tablet/_batch_download?check=true", endpoint);
    auto check_support_cb = [&url](HttpClient* client) {
        RETURN_IF_ERROR(client->init(url));
        client->set_timeout_ms(CHECK_SUPPORT_TIMEOUT * 1000);
        client->set_method(HttpMethod::HEAD);
        std::string response;
        return client->execute(&response);
    };
    return HttpClient::execute_with_retry(DOWNLOAD_FILE_MAX_RETRY, 1, check_support_cb);
}

Status list_remote_files_v2(const std::string& address, const std::string& token,
                            const std::string& remote_dir,
                            std::vector<std::pair<std::string, size_t>>* file_info_list) {
    std::string remote_url =
            fmt::format("http://{}/api/_tablet/_batch_download?token={}&dir={}&list=true", address,
                        token, remote_dir);

    std::string file_list_str;
    auto list_files_cb = [&](HttpClient* client) {
        file_list_str.clear();
        RETURN_IF_ERROR(client->init(remote_url, false));
        client->set_method(HttpMethod::GET);
        client->set_timeout_ms(LIST_REMOTE_FILE_TIMEOUT * 1000);
        return client->execute(&file_list_str);
    };
    Status status = HttpClient::execute_with_retry(DOWNLOAD_FILE_MAX_RETRY, 1, list_files_cb);
    if (!status.ok()) {
        LOG(WARNING) << "failed to list remote files from " << remote_url
                     << ", status: " << status.to_string() << ", response: " << file_list_str;
        return status;
    }

    std::vector<std::string> file_list =
            absl::StrSplit(file_list_str, "\n", absl::SkipWhitespace());
    if (file_list.size() % 2 != 0) {
        return Status::InternalError("batch download files: invalid file list, size is not even");
    }

    VLOG_DEBUG << "list remote files from " << remote_url
               << ", file count: " << file_list.size() / 2;

    for (size_t i = 0; i < file_list.size(); i += 2) {
        uint64_t file_size = 0;
        try {
            file_size = std::stoull(file_list[i + 1]);
        } catch (std::exception&) {
            return Status::InternalError("batch download files: invalid file size format: " +
                                         file_list[i + 1]);
        }
        file_info_list->emplace_back(std::move(file_list[i]), file_size);
    }

    return Status::OK();
}

Status download_files_v2(const std::string& address, const std::string& token,
                         const std::string& remote_dir, const std::string& local_dir,
                         const std::vector<std::pair<std::string, size_t>>& file_info_list) {
    std::string remote_url = fmt::format("http://{}/api/_tablet/_batch_download?dir={}&token={}",
                                         address, remote_dir, token);

    size_t batch_file_size = 0;
    std::unordered_set<std::string> expected_files;
    std::stringstream ss;
    for (const auto& file_info : file_info_list) {
        ss << file_info.first << "\n";
        batch_file_size += file_info.second;
        expected_files.insert(file_info.first);
    }
    std::string payload = ss.str();

    uint64_t estimate_timeout = batch_file_size / config::download_low_speed_limit_kbps / 1024;
    if (estimate_timeout < config::download_low_speed_time) {
        estimate_timeout = config::download_low_speed_time;
    }

    LOG(INFO) << "begin to download files from " << remote_url << " to " << local_dir
              << ", file count: " << file_info_list.size() << ", total size: " << batch_file_size
              << ", timeout: " << estimate_timeout;

    auto callback = [&](HttpClient* client) -> Status {
        RETURN_IF_ERROR(client->init(remote_url, false));
        client->set_method(HttpMethod::POST);
        client->set_payload(payload);
        client->set_timeout_ms(estimate_timeout * 1000);
        RETURN_IF_ERROR(client->download_multi_files(local_dir, expected_files));
        for (auto&& [file_name, file_size] : file_info_list) {
            std::string local_file_path = local_dir + "/" + file_name;

            std::error_code ec;
            // Check file length
            uint64_t local_file_size = std::filesystem::file_size(local_file_path, ec);
            if (ec) {
                LOG(WARNING) << "download file error: " << ec.message();
                return Status::IOError("can't retrive file_size of {}, due to {}", local_file_path,
                                       ec.message());
            }
            if (local_file_size != file_size) {
                LOG(WARNING) << "download file length error"
                             << ", remote_path=" << mask_token(remote_url)
                             << ", file_name=" << file_name << ", file_size=" << file_size
                             << ", local_file_size=" << local_file_size;
                return Status::InternalError("downloaded file size is not equal");
            }
            RETURN_IF_ERROR(io::global_local_filesystem()->permission(
                    local_file_path, io::LocalFileSystem::PERMS_OWNER_RW));
        }

        return Status::OK();
    };
    return HttpClient::execute_with_retry(DOWNLOAD_FILE_MAX_RETRY, 1, callback);
}

} // namespace doris
