package me.qwq.doghouse.util;

import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CityResponse;
import com.maxmind.geoip2.record.Subdivision;

import lombok.extern.slf4j.Slf4j;
import me.qwq.doghouse.pojo.bo.IpInfo;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;

import org.apache.commons.lang3.StringUtils;

@Slf4j
public class GeoIPUtil {

    private static DatabaseReader cityReader;
    public static String LOCALE = "zh-CN";

    static {
        try {
            InputStream geoLite2CityResourceStream = SmartResourceResolver.loadResource("/conf/extra/GeoLite2-City.mmdb");
            cityReader = new DatabaseReader.Builder(geoLite2CityResourceStream).build();
        } catch (IOException e) {
            throw new RuntimeException("IP 地址库初始化失败", e);
        }
    }
    
    /**
     * 以 IPv4 为准
     * @param ipInfo
     */
    public static IpInfo queryIpInfoGeoLite(IpInfo ipInfo) {
        try {
            InetAddress ipAddress;
            if (!StringUtils.isBlank(ipInfo.getIpv4())) {
                ipAddress = InetAddress.getByName(ipInfo.getIpv4());
            }
            else if (!StringUtils.isBlank(ipInfo.getIpv6())) {
                ipAddress = InetAddress.getByName(ipInfo.getIpv6());
            }
            else {
                log.warn("IpInfo 不包含 IPv4 或 IPv6 的任何之一, 无法获取归属地");
                return ipInfo;
            }
            CityResponse response = cityReader.city(ipAddress);
            
            if (response.getCountry() != null) {
                String countryStr = response.getCountry().getNames().get(LOCALE);
                ipInfo.setCountry(countryStr);
            }
            
            if (response.getSubdivisions() != null && !response.getSubdivisions().isEmpty()) {
                // 省
                Subdivision subdivision = response.getSubdivisions().get(0);
                if (subdivision != null) {
                    String subdivisionStr = subdivision.getNames().get(LOCALE);
                    ipInfo.setSubdivision(subdivisionStr);
                }
            }
            if (response.getCity() != null) {
                // 市
                String cityStr = response.getCity().getNames().get(LOCALE);
                ipInfo.setCity(cityStr);
            }
        } catch (IOException | GeoIp2Exception e) {
            log.warn("Get city response from GeoLite2-City database failed: {}", e.getMessage());
        }
        //log.debug("ipInfo: {}", ipInfo);
        return ipInfo;
    }
    
    public static void main(String[] args) {
        System.out.format("GeoLite2-City %s\r\n", queryIpInfoGeoLite(new IpInfo().setIp("46.3.98.216")));
    }
}