package com.pig4cloud.pig.marketing.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pig.marketing.api.dto.MktMgmtHandPushQueryDTO;
import com.pig4cloud.pig.marketing.api.dto.MktMgmtPushRecordSaveDTO;
import com.pig4cloud.pig.marketing.api.dto.config.SaveGlobalRuleDTO;
import com.pig4cloud.pig.marketing.api.dto.config.PushAPPDTO;
import com.pig4cloud.pig.marketing.api.entity.MktMgmtPushRecord;
import com.pig4cloud.pig.marketing.api.entity.mongo.Device;
import com.pig4cloud.pig.marketing.api.service.MktMgmtHandPushService;
import com.pig4cloud.pig.marketing.api.vo.rule.push.HandPushVO;
import com.pig4cloud.pig.marketing.config.PushValidationConfig;
import com.pig4cloud.pig.marketing.mapper.MktMgmtPushRecordMapper;
import com.pig4cloud.pig.marketing.service.MarketingConfigService;
import com.pig4cloud.pig.marketing.service.TcpDataService;
import com.pig4cloud.pig.marketing.util.DeviceInfoUtil;
import com.pig4cloud.pig.marketing.util.IPLocationUtil;
import com.pig4cloud.pig.marketing.util.PushFrequencyUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 手动推送服务实现类
 * 
 * @author WCL
 * @date 2025-09-04
 * @description 手动推送相关业务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MktMgmtHandPushServiceImpl implements MktMgmtHandPushService {

    private final MktMgmtPushRecordMapper mktMgmtPushRecordMapper;
    private final MarketingConfigService marketingConfigService;
    @Autowired
    @Lazy
    private TcpDataService tcpDataService;
    private final IPLocationUtil ipLocationUtil;
    private final DeviceInfoUtil deviceInfoUtil;
    private final PushValidationConfig pushValidationConfig;
    private final RedisTemplate<String, Object> redisTemplate;

    @Override
    public Page<HandPushVO> pageQuery(MktMgmtHandPushQueryDTO queryDTO) {
        Page<MktMgmtPushRecord> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        
        LambdaQueryWrapper<MktMgmtPushRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MktMgmtPushRecord::getDelFlag, "0");
        queryWrapper.eq(MktMgmtPushRecord::getAutoPush, 1);
        
        // 根据时间范围查询
        if (StringUtils.hasText(queryDTO.getStartTime())) {
            LocalDateTime startTime = LocalDateTime.parse(queryDTO.getStartTime() + " 00:00:00", 
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            queryWrapper.ge(MktMgmtPushRecord::getCreateTime, startTime);
        }
        
        if (StringUtils.hasText(queryDTO.getEndTime())) {
            LocalDateTime endTime = LocalDateTime.parse(queryDTO.getEndTime() + " 23:59:59", 
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            queryWrapper.le(MktMgmtPushRecord::getCreateTime, endTime);
        }
        
        queryWrapper.orderByDesc(MktMgmtPushRecord::getCreateTime);
        
        Page<MktMgmtPushRecord> recordPage = mktMgmtPushRecordMapper.selectPage(page, queryWrapper);
        
        // 转换为HandPushVO
        Page<HandPushVO> voPage = new Page<>(recordPage.getCurrent(), recordPage.getSize(), recordPage.getTotal());
        List<HandPushVO> voList = recordPage.getRecords().stream()
            .map(this::convertToHandPushVO)
            .collect(Collectors.toList());
        voPage.setRecords(voList);
        
        return voPage;
    }

    @Override
    public String handPush(MktMgmtPushRecordSaveDTO saveDTO) {
        try {
            log.info("开始手动推送，推送内容：{}，客户端ID：{}", saveDTO.getPushContent(), saveDTO.getClientId());
            
            // 1. 获取全局手动推送规则
            SaveGlobalRuleDTO globalRule = marketingConfigService.getGlobalRule();
            if (globalRule == null) {
                return "获取全局手动推送规则失败";
            }
            
            // 2. IP校验（配置化控制）
            if (pushValidationConfig.getEnableIpCheck() && !validateGlobalRuleIP(globalRule.getIp(), saveDTO.getPushIP())) {
                return "推送IP【" + saveDTO.getPushIP() + "】不在允许的IP范围内";
            }
            
            // 3. 地址校验 - 根据IP获取三级地址信息并匹配pushAddr
            if (pushValidationConfig.getEnableAddressCheck() && 
                globalRule.getPushAddr() != null && !globalRule.getPushAddr().isEmpty()) {

				if (!"All".equals(globalRule.getPushAddr().get(0))){
					String fullAddress = ipLocationUtil.getCityByIP(saveDTO.getPushIP());
					if (fullAddress == null) {
						return "无法解析推送IP【" + saveDTO.getPushIP() + "】的地址信息";
					}

					// 检查是否匹配pushAddr中的任一地址
					boolean addressMatched = false;
					for (String allowedAddr : globalRule.getPushAddr()) {
						if (isAddressMatched(fullAddress, allowedAddr)) {
							addressMatched = true;
							break;
						}
					}

					if (!addressMatched) {
						return "推送地址【" + fullAddress + "】不在允许的地址范围内，允许的地址：" + globalRule.getPushAddr();
					}
					log.info("地址校验通过，IP：{}，地址：{}", saveDTO.getPushIP(), fullAddress);
				}

				log.info("地址校验通过，ALL-----");
            }
            
            // 4. 应用校验 - 根据客户端ID获取设备信息并匹配pushApp和pushBundle
            if (pushValidationConfig.getEnableAppCheck()) {
                Device device = tcpDataService.getDeviceByClientID(saveDTO.getClientId());
                if (device == null) {
                    return "未找到客户端ID【" + saveDTO.getClientId() + "】对应的设备信息";
                }
                
                String[] bundleAndAppId = deviceInfoUtil.extractBundleAndAppId(device.getDeviceInfo());
                String bundle = bundleAndAppId[0];
                String appId = bundleAndAppId[1];
                
                boolean appMatched = false;
                String matchedType = "";
                
                // 检查pushApp（appId匹配）
                if (!pushValidationConfig.getEnableBundleCheck() && globalRule.getPushApp() != null && !globalRule.getPushApp().isEmpty() && appId != null) {
                    // 检查是否为All
                    if (globalRule.getPushApp().stream()
                            .anyMatch(pushApp -> pushApp != null && "All".equals(pushApp.getAppId()))) {
                        appMatched = true;
                        matchedType = "appId(All)";
                    } else {
                        // 检查appId是否匹配
                        if (globalRule.getPushApp().stream()
                                .anyMatch(pushApp -> pushApp != null && appId.equals(pushApp.getAppId()))) {
                            appMatched = true;
                            matchedType = "appId";
                        }
                    }
                }
                
                // 检查pushBundle（bundle匹配）
                if ( !appMatched && pushValidationConfig.getEnableBundleCheck() && globalRule.getPushBundle() != null && !globalRule.getPushBundle().isEmpty() && bundle != null) {
                    if (globalRule.getPushBundle().contains(bundle)) {
                        appMatched = true;
                        matchedType = "bundle";
                    }
                }
                
                if (!appMatched) {
                    StringBuilder allowedApps = new StringBuilder();
                    if (globalRule.getPushApp() != null && !globalRule.getPushApp().isEmpty()) {
                        allowedApps.append("允许的appId：").append(globalRule.getPushApp().stream().map(PushAPPDTO::getAppId).toList());
                    }
                    if (globalRule.getPushBundle() != null && !globalRule.getPushBundle().isEmpty()) {
                        if (allowedApps.length() > 0) {
                            allowedApps.append("，");
                        }
                        allowedApps.append("允许的bundle：").append(globalRule.getPushBundle());
                    }
                    return "应用校验失败，bundle【" + bundle + "】和appId【" + appId + "】都不在允许的应用范围内，" + allowedApps.toString();
                }
                log.info("应用校验通过，匹配类型：{}，bundle：{}，appId：{}", matchedType, bundle, appId);
            }
            
            // 5. 校验域名
            if (pushValidationConfig.getEnableDomainCheck() && 
                !validateGlobalRuleDomain(globalRule.getDomain(), saveDTO.getPushDomain())) {
                return "推送域名【" + saveDTO.getPushDomain() + "】不在允许的域名范围内";
            }
            
            // 6. 校验推送频率
            if (pushValidationConfig.getEnableFrequencyCheck() && 
                !PushFrequencyUtil.checkPushFrequency(globalRule.getPushFrequency(), 0L, saveDTO.getClientId(), redisTemplate)) {
                return "推送频率检查未通过，推送频率：" + globalRule.getPushFrequency();
            }
            
            // 7. 构建推送记录
            MktMgmtPushRecord pushRecord = buildHandPushRecord(saveDTO, globalRule);
            
            // 8. 保存推送记录
            int result = mktMgmtPushRecordMapper.insert(pushRecord);
            if (result > 0) {
                log.info("手动推送成功，推送内容：{}，客户端ID：{}", saveDTO.getPushContent(), saveDTO.getClientId());
                return "手动推送成功";
            } else {
                return "手动推送失败，数据库保存异常";
            }
            
        } catch (Exception e) {
            log.error("手动推送异常，推送内容：{}，客户端ID：{}", saveDTO.getPushContent(), saveDTO.getClientId(), e);
            return "手动推送异常：" + e.getMessage();
        }
    }
    
    /**
     * 校验全局规则IP
     * 
     * @param allowedIPs 允许的IP列表
     * @param pushIP 推送IP
     * @return 是否匹配
     */
    private boolean validateGlobalRuleIP(List<String> allowedIPs, String pushIP) {
        if (allowedIPs == null || allowedIPs.isEmpty()) {
            return true; // 如果没有配置IP限制，则允许
        }
        
        if (pushIP == null || pushIP.trim().isEmpty()) {
            return false; // 推送IP为空，不允许
        }
        
        for (String allowedIP : allowedIPs) {
            if (allowedIP.contains("/")) {
                // IP段格式：192.168.10.101/110
                String[] ipRange = allowedIP.split("/");
                if (ipRange.length == 2) {
                    String startIP = ipRange[0].trim();
                    String endIPPart = ipRange[1].trim();
                    
                    // 构建结束IP：将最后一个数字替换为endIPPart
                    String[] startIPParts = startIP.split("\\.");
                    if (startIPParts.length == 4) {
                        String endIP = startIPParts[0] + "." + startIPParts[1] + "." + startIPParts[2] + "." + endIPPart;
                        if (isIPInRange(pushIP, startIP, endIP)) {
                            return true;
                        }
                    }
                }
            } else {
                // 单个IP格式：192.168.10.102
                if (pushIP.equals(allowedIP.trim())) {
                    return true;
                }
            }
        }
        
        return false;
    }
    
    /**
     * 校验全局规则域名
     * 
     * @param allowedDomains 允许的域名列表
     * @param pushDomain 推送域名
     * @return 是否匹配
     */
    private boolean validateGlobalRuleDomain(List<String> allowedDomains, String pushDomain) {
        if (allowedDomains == null || allowedDomains.isEmpty()) {
            return true; // 如果没有配置域名限制，则允许
        }
        
        if (pushDomain == null || pushDomain.trim().isEmpty()) {
            return false; // 推送域名为空，不允许
        }
        
        for (String allowedDomain : allowedDomains) {
            if (pushDomain.equals(allowedDomain.trim())) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 判断IP是否在指定范围内
     * 
     * @param ip 要检查的IP
     * @param startIP 起始IP
     * @param endIP 结束IP
     * @return 是否在范围内
     */
    private boolean isIPInRange(String ip, String startIP, String endIP) {
        try {
            long ipLong = ipToLong(ip);
            long startIPLong = ipToLong(startIP);
            long endIPLong = ipToLong(endIP);
            return ipLong >= startIPLong && ipLong <= endIPLong;
        } catch (Exception e) {
            log.warn("IP范围检查异常，IP：{}，起始IP：{}，结束IP：{}", ip, startIP, endIP, e);
            return false;
        }
    }
    
    /**
     * 将IP地址转换为Long类型
     * 
     * @param ip IP地址
     * @return Long值
     */
    private long ipToLong(String ip) {
        String[] parts = ip.split("\\.");
        if (parts.length != 4) {
            throw new IllegalArgumentException("Invalid IP address: " + ip);
        }
        
        long result = 0;
        for (int i = 0; i < 4; i++) {
            int part = Integer.parseInt(parts[i]);
            if (part < 0 || part > 255) {
                throw new IllegalArgumentException("Invalid IP address: " + ip);
            }
            result = result * 256 + part;
        }
        return result;
    }
    
    /**
     * 构建手动推送记录
     * 
     * @param saveDTO 保存参数
     * @param globalRule 全局规则信息
     * @return 推送记录
     */
    private MktMgmtPushRecord buildHandPushRecord(MktMgmtPushRecordSaveDTO saveDTO, SaveGlobalRuleDTO globalRule) {
        MktMgmtPushRecord pushRecord = new MktMgmtPushRecord();
        
        // 基本信息
        pushRecord.setRuleId(0L); // 全局规则ID为0
        pushRecord.setRuleName("全局手动推送规则");
        pushRecord.setPushContent(globalRule.getPushContent());
		pushRecord.setClientId(saveDTO.getClientId());
        pushRecord.setAutoPush(1);
        pushRecord.setPushStatus(true);
		pushRecord.setPushFrequency(globalRule.getPushFrequency());
		pushRecord.setPushType(globalRule.getPushType());
		pushRecord.setPushAction(globalRule.getAction());
		pushRecord.setDelayPush(Integer.valueOf(globalRule.getDelayPush()));
		pushRecord.setPushAddr(saveDTO.getPushIP());
        pushRecord.setCreateTime(LocalDateTime.now());
        pushRecord.setUpdateTime(LocalDateTime.now());
        
        // 构建触发条件JSON
        Map<String, Object> triggerCondition = new HashMap<>();
        triggerCondition.put("type", "manual");
        triggerCondition.put("ruleId", 0L);
        triggerCondition.put("ruleName", "全局手动推送规则");
        triggerCondition.put("pushFrequency", globalRule.getPushFrequency());
        triggerCondition.put("allowedIPs", globalRule.getIp());
        triggerCondition.put("allowedDomains", globalRule.getDomain());
        pushRecord.setTriggerCondition(triggerCondition.toString());
        
        // 构建推送详情JSON
        Map<String, Object> pushDetail = new HashMap<>();
        pushDetail.put("pushType", "manual");
        pushDetail.put("pushAction", globalRule.getAction());
        pushDetail.put("pushContent", saveDTO.getPushContent());
        pushDetail.put("pushIP", saveDTO.getPushIP());
        pushDetail.put("pushDomain", saveDTO.getPushDomain());
        pushDetail.put("pushTime", LocalDateTime.now().toString());
        pushDetail.put("delayPush", globalRule.getDelayPush());
        pushRecord.setPushDetail(pushDetail.toString());
        
        return pushRecord;
    }
    

    
    /**
     * 转换为HandPushVO
     * 
     * @param record 推送记录
     * @return HandPushVO
     */
    private HandPushVO convertToHandPushVO(MktMgmtPushRecord record) {
        HandPushVO vo = new HandPushVO();
        BeanUtils.copyProperties(record, vo);
        return vo;
    }
    
    /**
     * 检查地址是否匹配
     * 
     * @param fullAddress 完整的三级地址，格式：国家-省-市
     * @param allowedAddr 允许的地址配置
     * @return 是否匹配
     */
    private boolean isAddressMatched(String fullAddress, String allowedAddr) {
        if (fullAddress == null || allowedAddr == null) {
            return false;
        }
        
        // 如果允许的地址配置为空，则不匹配
        if (allowedAddr.trim().isEmpty()) {
            return false;
        }
        
        String trimmedAllowedAddr = allowedAddr.trim();
        
        // 1. 完全匹配
        if (fullAddress.equals(trimmedAllowedAddr)) {
            return true;
        }
        
        // 2. 检查是否匹配国家级别（如果允许的地址只有国家）
        if (!trimmedAllowedAddr.contains("-")) {
            return fullAddress.startsWith(trimmedAllowedAddr + "-");
        }
        
        // 3. 检查是否匹配国家-省级别
        String[] allowedParts = trimmedAllowedAddr.split("-");
        String[] fullParts = fullAddress.split("-");
        
        if (allowedParts.length == 2 && fullParts.length >= 2) {
            return allowedParts[0].equals(fullParts[0]) && allowedParts[1].equals(fullParts[1]);
        }
        
        // 4. 检查是否匹配国家-省-市级别
        if (allowedParts.length == 3 && fullParts.length >= 3) {
            return allowedParts[0].equals(fullParts[0]) && 
                   allowedParts[1].equals(fullParts[1]) && 
                   allowedParts[2].equals(fullParts[2]);
        }
        
        return false;
    }
}
