// 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 "common/network_util.h"

#include <arpa/inet.h>
#include <butil/endpoint.h>
#include <butil/strings/string_split.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>

#include <sstream>
#include <vector>

#include "common/config.h"
#include "common/defer.h"
#include "common/logging.h"

namespace doris::cloud {

class CIDR {
public:
    CIDR() : address_(0), netmask_(0xffffffff) {}
    bool reset(const std::string& cidr_str) {
        address_ = 0;
        netmask_ = 0xffffffff;

        // check if have mask
        std::string cidr_format_str = cidr_str;
        int32_t have_mask = cidr_str.find("/");
        if (have_mask == -1) {
            cidr_format_str.assign(cidr_str + "/32");
        }
        VLOG_DEBUG << "cidr format str: " << cidr_format_str;

        std::vector<std::string> cidr_items;
        butil::SplitString(cidr_format_str, '/', &cidr_items);
        if (cidr_items.size() != 2) {
            LOG(WARNING) << "wrong CIDR format. network=" << cidr_str;
            return false;
        }

        if (cidr_items[1].empty()) {
            LOG(WARNING) << "wrong CIDR mask format. network=" << cidr_str;
            return false;
        }

        char* endptr = nullptr;
        int32_t mask_length = strtol(cidr_items[1].c_str(), &endptr, 10);
        if (errno != 0 && mask_length == 0) {
            char errmsg[64];
            // Ignore unused return value
            auto ret = strerror_r(errno, errmsg, 64);
            LOG(WARNING) << "wrong CIDR mask format. network=" << cidr_str
                         << ", mask_length=" << mask_length << ", errno=" << errno
                         << ", errmsg=" << errmsg << ", strerror_r returns=" << ret;
            return false;
        }
        if (mask_length <= 0 || mask_length > 32) {
            LOG(WARNING) << "wrong CIDR mask format. network=" << cidr_str
                         << ", mask_length=" << mask_length;
            return false;
        }

        uint32_t address = 0;
        if (!ip_to_int(cidr_items[0], &address)) {
            LOG(WARNING) << "wrong CIDR IP value. network=" << cidr_str;
            return false;
        }
        address_ = address;

        netmask_ = 0xffffffff;
        netmask_ = netmask_ << (32 - mask_length);
        return true;
    }
    bool contains(const std::string& ip) {
        uint32_t ip_int = 0;
        if (!ip_to_int(ip, &ip_int)) {
            return false;
        }
        if ((address_ & netmask_) == (ip_int & netmask_)) {
            return true;
        }
        return false;
    }

private:
    bool ip_to_int(const std::string& ip_str, uint32_t* value) {
        struct in_addr addr;
        int flag = inet_aton(ip_str.c_str(), &addr);
        if (flag == 0) {
            return false;
        }
        *value = ntohl(addr.s_addr);
        return true;
    }

    uint32_t address_;
    uint32_t netmask_;
};

class InetAddress {
public:
    InetAddress(struct sockaddr* addr) { this->addr_ = *(struct sockaddr_in*)addr; }
    bool is_address_v4() const { return addr_.sin_family == AF_INET; }
    bool is_loopback_v4() const {
        in_addr_t s_addr = addr_.sin_addr.s_addr;
        return (ntohl(s_addr) & 0xFF000000) == 0x7F000000;
    }
    std::string get_host_address_v4() {
        char addr_buf[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &(addr_.sin_addr), addr_buf, INET_ADDRSTRLEN);
        return std::string(addr_buf);
    }

private:
    struct sockaddr_in addr_;
};

static bool get_hosts_v4(std::vector<InetAddress>* hosts) {
    ifaddrs* if_addrs = nullptr;
    if (getifaddrs(&if_addrs)) {
        std::stringstream ss;
        char buf[64];
        LOG(FATAL) << "getifaddrs failed because " << strerror_r(errno, buf, sizeof(buf));
        return false;
    }

    for (ifaddrs* if_addr = if_addrs; if_addr != nullptr; if_addr = if_addr->ifa_next) {
        if (!if_addr->ifa_addr) {
            continue;
        }
        if (if_addr->ifa_addr->sa_family == AF_INET) { // check it is IP4
            // is a valid IP4 Address
            hosts->emplace_back(if_addr->ifa_addr);
        }
    }

    if (if_addrs != nullptr) {
        freeifaddrs(if_addrs);
    }

    return true;
}

std::string get_local_ip(const std::string& priority_networks) {
    std::string localhost_str = butil::my_ip_cstr();
    DORIS_CLOUD_DEFER {
        // Check if ip eq 127.0.0.1, ms/recycler exit
        LOG(INFO) << "get the IP for ms is " << localhost_str;
        if (config::enable_loopback_address_for_ms || localhost_str != "127.0.0.1") return;
        LOG(WARNING) << "localhost IP is loopback address (127.0.0.1), "
                     << "there may be multiple NICs for use, "
                     << "please set priority_networks with a CIDR expression in doris_cloud.conf "
                     << "to choose a non-loopback address accordingly";
        LOG(WARNING) << "process will exit ...";
        exit(-1);
    };
    if (priority_networks == "") {
        LOG(INFO) << "use butil::my_ip_cstr(), local host ip=" << localhost_str;
        return localhost_str;
    }
    std::vector<CIDR> priority_cidrs;
    LOG(INFO) << "priority CIDRs: " << priority_networks;
    std::vector<std::string> cidr_strs;
    butil::SplitString(priority_networks, ';', &cidr_strs);
    for (auto& cidr_str : cidr_strs) {
        CIDR cidr;
        if (!cidr.reset(cidr_str)) {
            LOG(FATAL) << "wrong cidr format. cidr_str=" << cidr_str;
            return localhost_str;
        }
        priority_cidrs.push_back(cidr);
    }

    std::vector<InetAddress> hosts;
    if (!get_hosts_v4(&hosts)) {
        LOG(FATAL) << "failed to getifaddrs";
        return localhost_str;
    }

    if (hosts.empty()) {
        LOG(FATAL) << "failed to get host";
        return localhost_str;
    }

    auto is_in_prior_network = [&priority_cidrs](const std::string& ip) {
        for (auto& cidr : priority_cidrs) {
            if (cidr.contains(ip)) {
                return true;
            }
        }
        return false;
    };

    std::string loopback;
    localhost_str = "";
    for (auto addr_it = hosts.begin(); addr_it != hosts.end(); ++addr_it) {
        if ((*addr_it).is_address_v4()) {
            VLOG_DEBUG << "check ip=" << addr_it->get_host_address_v4();
            if ((*addr_it).is_loopback_v4()) {
                loopback = addr_it->get_host_address_v4();
            } else if (!priority_cidrs.empty()) {
                if (is_in_prior_network(addr_it->get_host_address_v4())) {
                    localhost_str = addr_it->get_host_address_v4();

                    break;
                }
            } else {
                localhost_str = addr_it->get_host_address_v4();
                break;
            }
        }
    }
    if (!localhost_str.empty()) {
        LOG(INFO) << "local host ip=" << localhost_str;
        return localhost_str;
    }

    if (!loopback.empty()) {
        localhost_str = loopback;
        LOG(WARNING) << "fail to find one valid non-loopback address, use loopback address: "
                     << localhost_str;
    } else {
        localhost_str = butil::my_ip_cstr();
        LOG(WARNING)
                << "fail to find valid address of priority cidrs in conf, use butil::my_ip_cstr(): "
                << localhost_str;
    }

    return localhost_str;
}

} // namespace doris::cloud
