package com.pig4cloud.pig.marketing.util;

import com.pig4cloud.pig.common.core.util.ip.IPUtils;
import com.pig4cloud.pig.marketing.config.PushValidationConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * IP地址解析工具类
 * 
 * @author WCL
 * @date 2025-09-04
 * @description 根据IP地址获取地理位置信息
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class IPLocationUtil {

    private final PushValidationConfig pushValidationConfig;
    private final RedisTemplate<String, Object> redisTemplate;
    
    // ip2region搜索器，用于获取完整的三级地址信息
    private static Searcher searcher;
    
    static {
        initIpSearcher();
    }
    
    /**
     * 初始化IP地址索引
     */
	private static void initIpSearcher() {
		try {
			// 1) 外部路径优先：系统属性 ip2region.db 或 环境变量 IP2REGION_DB_PATH
			String externalPath = System.getProperty("ip2region.db");
			if (externalPath == null || externalPath.trim().isEmpty()) {
				externalPath = System.getenv("IP2REGION_DB_PATH");
			}
			if (externalPath != null && !externalPath.trim().isEmpty()) {
				searcher = Searcher.newWithFileOnly(externalPath.trim());
				log.info("IPLocationUtil ip2region初始化成功 (external path: {})", externalPath);
				return;
			}

			// 2) 从classpath读取写入临时文件，再基于文件初始化
			try (InputStream is = IPLocationUtil.class.getClassLoader().getResourceAsStream("ip/ip2region.xdb")) {
				if (is == null) {
					log.error("IPLocationUtil ip2region资源不存在: ip/ip2region.xdb");
					searcher = null;
					return;
				}
				byte[] cBuff = is.readAllBytes();
				java.nio.file.Path tmp = java.nio.file.Files.createTempFile("ip2region", ".xdb");
				java.nio.file.Files.write(tmp, cBuff);
				subtleSetDeleteOnExit(tmp);
				searcher = Searcher.newWithFileOnly(tmp.toString());
				log.info("IPLocationUtil ip2region初始化成功 (temp file: {})", tmp);
			}
		} catch (Exception e) {
			log.error("IPLocationUtil ip2region初始化失败", e);
			searcher = null;
		}
	}

	/**
	 * 尝试标记临时文件在JVM退出时删除
	 */
	private static void subtleSetDeleteOnExit(java.nio.file.Path tmp) {
		try {
			java.io.File f = tmp.toFile();
			f.deleteOnExit();
		} catch (Exception ignore) {
			// no-op
		}
	}

    /**
     * 根据IP地址获取三级地址信息
     * 
     * @param ip IP地址
     * @return 三级地址信息，格式：国家-省-市，如：中国-广东省-深圳市
     */
    public String getCityByIP(String ip) {
        if (ip == null || ip.trim().isEmpty()) {
            return null;
        }
        
        try {
            // 检查是否启用IP定位
            if (!pushValidationConfig.getIpLocation().getEnabled()) {
                return null;
            }
            
            // 检查缓存
            String cacheKey = "ip:location:" + ip;
            if (pushValidationConfig.getIpLocation().getEnableCache()) {
                String cachedResult = (String) redisTemplate.opsForValue().get(cacheKey);
                if (cachedResult != null) {
                    log.debug("从缓存获取IP地址信息，IP：{}，地址：{}", ip, cachedResult);
                    return cachedResult;
                }
            }
            
            // 检查IP合法性
            if (!IPUtils.isValidIp(ip)) {
                log.warn("IP地址格式不正确：{}", ip);
                return null;
            }
            
            // 检查是否为内网IP
/*            if (IPUtils.isIntranetIp(ip)) {
                String result = "内网IP";
                cacheResult(cacheKey, result);
                return result;
            }*/
            
            // 使用ip2region获取完整的三级地址信息
            log.info("IPLocationUtil 开始解析IP: {}", ip);
            String fullAddress = getFullAddressFromIp2region(ip);
            if (fullAddress != null) {
                log.info("IPLocationUtil 解析结果: {} -> {}", ip, fullAddress);
                cacheResult(cacheKey, fullAddress);
                return fullAddress;
            }
            
            // 如果无法解析，返回null表示匹配不通过
				log.warn("无法解析IP地址：{}", ip);
            return null;
            
        } catch (Exception e) {
            log.error("IP地址解析异常，IP：{}", ip, e);
            return null;
        }
    }
    
    /**
     * 使用ip2region获取完整的三级地址信息
     * 
     * @param ip IP地址
     * @return 三级地址信息，格式：国家-省-市
     */
    private String getFullAddressFromIp2region(String ip) {
        try {
            // 统一委托给 IPUtils，避免本地 Searcher 与库/数据版本不一致
            String region = IPUtils.getIpRegion(ip);
            log.info("IPLocationUtil 调用 IPUtils.getIpRegion 返回: ip={}, region={}", ip, region);
            if (region == null || region.trim().isEmpty() || "未知".equals(region) || "内网".equals(region)) {
                return null;
            }

            // IPUtils 返回通常为 "国家-省" 或仅 "国家"
            List<String> arr = cn.hutool.core.util.StrUtil.split(region, '-');
            String country = arr.size() >= 1 ? arr.get(0) : null;
            String province = arr.size() >= 2 ? arr.get(1) : null;

            if (country == null || country.trim().isEmpty()) {
                return null;
            }

            StringBuilder address = new StringBuilder();
            address.append(country);
            if (province != null && !province.trim().isEmpty()) {
                address.append("-").append(province).append("-").append(province);
            } else {
                // 没有省份信息，用国家补齐三级
                address.append("-").append(country).append("-").append(country);
            }
            return address.toString();
        } catch (Exception e) {
            log.warn("查询IP[{}]归属地出错", ip, e);
        }
        return null;
    }
    
    /**
     * 缓存结果
     * 
     * @param cacheKey 缓存键
     * @param result 结果
     */
    private void cacheResult(String cacheKey, String result) {
        if (pushValidationConfig.getIpLocation().getEnableCache()) {
            try {
                redisTemplate.opsForValue().set(cacheKey, result, 
                    pushValidationConfig.getIpLocation().getCacheExpireSeconds(), TimeUnit.SECONDS);
            } catch (Exception e) {
                log.warn("缓存IP地址信息失败，key：{}，result：{}", cacheKey, result, e);
            }
        }
    }
    
    
    
}
