package org.jeecg.modules.adweb.common.util;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.maxmind.db.CHMCache;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CityResponse;
import com.maxmind.geoip2.record.Country;
import com.maxmind.geoip2.record.Location;
import com.maxmind.geoip2.record.Subdivision;

import org.jeecg.modules.adweb.common.dto.CountryAreaApiDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * @description:
 * @author: Cyan
 * @time: 2019/12/16 10:33
 */
@Component
public class GeoIpUtil {

    private static final Logger log = LoggerFactory.getLogger(GeoIpUtil.class);
    // GEOIp数据库实例
    private static DatabaseReader reader = null;

    @Value("${geoip.static.city.mmdb}")
    private String geoipCityMmdb;

    /**
     * 获取数据库实例
     *
     * @param cityMmdb 可配的geoip城市静态数据库
     * @return
     * @author Cyan -- 2019/12/16 10:49
     */
    public DatabaseReader getDatabaseReader(String cityMmdb) {
        if (null == reader) {
            File database = new File(cityMmdb);
            try {
                reader = new DatabaseReader.Builder(database).withCache(new CHMCache()).build();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return reader;
    }

    /**
     * 根据ip解析国家/区域
     *
     * @param ip
     * @return 国家区域api对象
     * @author Cyan -- 2019/12/16 12:15
     */
    public CountryAreaApiDto getCountryAndAreaByIp(String ip) {
        CountryAreaApiDto dto = new CountryAreaApiDto();
        try {
            DatabaseReader reader = getDatabaseReader(geoipCityMmdb);
            if (reader == null) {
                return dto;
            }
            InetAddress ipAddress = InetAddress.getByName(ip);
            CityResponse response = reader.city(ipAddress);
            // 国家
            Country country = response.getCountry();
            dto.setCountryZhCN(country.getNames().get("zh-CN"));
            if ("香港".equals(country.getNames().get("zh-CN"))) {
                dto.setCountryZhCN("中国香港");
            }
            if ("台湾".equals(country.getNames().get("zh-CN"))) {
                dto.setCountryZhCN("中国台湾");
            }
            if ("澳门".equals(country.getNames().get("zh-CN"))) {
                dto.setCountryZhCN("中国澳门");
            }
            dto.setCountryIsoCode(country.getIsoCode());
            // 省份
            Subdivision subdivision = response.getMostSpecificSubdivision();
            dto.setSubdivisionIsoCode(subdivision.getIsoCode());
            dto.setSubdivisionZhCN(subdivision.getNames().get("zh-CN"));
            Location location = response.getLocation();
            location.getTimeZone();
            if (StringUtils.isNotBlank(location.getTimeZone())) {
                dto.setTimeZone(location.getTimeZone());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (GeoIp2Exception e) {
            e.printStackTrace();
        }
        return dto;
    }

    /**
     * 根据ip获取时区
     *
     * @param ip
     * @return 时区
     * @author Cyan -- 2020/3/9 10:58
     */
    public String getTimeZone(String ip) {
        String timeZero = "";
        try {
            DatabaseReader reader = getDatabaseReader(geoipCityMmdb);
            InetAddress ipAddress = InetAddress.getByName(ip);
            CityResponse response = reader.city(ipAddress);
            Location location = response.getLocation();
            timeZero = location.getTimeZone();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取ip时区失败", e);
        }
        return timeZero;
    }

    /**
     * 根据ip获取当地时区时间
     *
     * @param ip
     * @return
     * @author Cyan -- 2020/3/9 11:06
     */
    public Date getLocalhostTime(String ip, Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT);
        String timeZone = getTimeZone(ip);
        sdf.setTimeZone(
                StringUtils.isNotEmpty(timeZone)
                        ? TimeZone.getTimeZone(timeZone)
                        : TimeZone.getTimeZone(DateUtil.DEFAULT_ZONE_ID));

        String dateStr = sdf.format(date);
        Date res = new Date();
        try {
            res = DateUtil.parseDate(dateStr, DateUtil.DATE_TIME_FORMAT);
        } catch (Exception e) {
            log.error("获取ip时区时间失败", e);
        }
        return res;
    }
}
