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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pig.marketing.api.dto.MktMgmtPushRecordQueryDTO;
import com.pig4cloud.pig.marketing.api.dto.MktMgmtPushRecordSaveDTO;
import com.pig4cloud.pig.marketing.api.entity.*;
import com.pig4cloud.pig.marketing.api.vo.rule.StatKeywordVO;
import com.pig4cloud.pig.marketing.mapper.*;
import com.pig4cloud.pig.marketing.service.MktMgmtPushRecordService;
import com.pig4cloud.pig.marketing.util.PushFrequencyUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

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

/**
 * @author: lwh
 * @date: 2025-08-31
 * @description: 营销推送记录Service实现类
 */
@Slf4j
@Service
@AllArgsConstructor
public class MktMgmtPushRecordServiceImpl implements MktMgmtPushRecordService {

	private final MktMgmtPushRecordMapper mktMgmtPushRecordMapper;
	private final MktMgmtKeywordMapper mktMgmtKeywordMapper;
	private final MktMgmtRuleMapper mktMgmtRuleMapper;
	private final MktMgmtRuleIpMapper mktMgmtRuleIpMapper;
	private final MktMgmtRuleDomainMapper mktMgmtRuleDomainMapper;
	private final RedisTemplate<String, Object> redisTemplate;

	@Override
	public Page<MktMgmtPushRecord> pageQuery(MktMgmtPushRecordQueryDTO queryDTO) {
		log.info("分页查询营销推送记录，查询条件：{}", queryDTO);
		
		LambdaQueryWrapper<MktMgmtPushRecord> queryWrapper = new LambdaQueryWrapper<>();
		
		if (StringUtils.hasText(queryDTO.getRuleName())) {
			queryWrapper.like(MktMgmtPushRecord::getRuleName, queryDTO.getRuleName());
		}
		
		if (StringUtils.hasText(queryDTO.getTriggerCondition())) {
			queryWrapper.like(MktMgmtPushRecord::getTriggerCondition, queryDTO.getTriggerCondition());
		}

		queryWrapper.eq(MktMgmtPushRecord::getDelFlag, "0");
		queryWrapper.eq(MktMgmtPushRecord::getAutoPush, 0);
		
		queryWrapper.orderByDesc(MktMgmtPushRecord::getCreateTime);
		
		Page<MktMgmtPushRecord> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
		Page<MktMgmtPushRecord> result = mktMgmtPushRecordMapper.selectPage(page, queryWrapper);
		
		log.info("分页查询完成，总记录数：{}，当前页记录数：{}", result.getTotal(), result.getRecords().size());
		return result;
	}

		@Override
	public String saveRecord(MktMgmtPushRecordSaveDTO saveDTO) {
		log.info("新增营销推送记录，数据：{}", saveDTO);
		
		try {
			Map<Long, Integer> ruleMatchCounts = calculateRuleMatchCounts(saveDTO.getPushContent());
			if (ruleMatchCounts.isEmpty()) {
				log.warn("推送内容未匹配到任何关键字：{}", saveDTO.getPushContent());
				return "推送内容【" + saveDTO.getPushContent() + "】未匹配到任何关键字";
			}
			
			List<Map.Entry<Long, Integer>> sortedRules = ruleMatchCounts.entrySet().stream()
				.sorted(Map.Entry.<Long, Integer>comparingByValue().reversed())
				.collect(Collectors.toList());
			
			log.debug("按匹配次数排序的规则：{}", sortedRules);
			
			StringBuilder errorDetails = new StringBuilder();
			MktMgmtRule selectedRule = null;
			Long selectedRuleId = null;
			
			for (Map.Entry<Long, Integer> entry : sortedRules) {
				Long ruleId = entry.getKey();
				Integer matchCount = entry.getValue();
				
				log.debug("尝试规则{}，匹配次数：{}", ruleId, matchCount);
				
				MktMgmtRule rule = mktMgmtRuleMapper.selectById(ruleId);
				if (rule == null || "1".equals(rule.getDelFlag())) {
					log.warn("规则不存在或已删除，ruleId：{}", ruleId);
					errorDetails.append("规则").append(ruleId).append("不存在或已删除；");
					continue;
				}
				
				List<String> matchedKeywords = getMatchedKeywordsForRule(saveDTO.getPushContent(), ruleId);
				
				// 验证IP和域名规则
				ValidationResult validationResult = validateRuleIpAndDomainWithDetails(ruleId, saveDTO.getPushIP(), saveDTO.getPushDomain());
				
				if (validationResult.isValid()) {
					// 验证推送频率
					boolean shouldPush = PushFrequencyUtil.checkPushFrequency(rule.getPushFrequency(), rule.getId(), saveDTO.getClientId(), redisTemplate);
					if (shouldPush) {
						selectedRule = rule;
						selectedRuleId = ruleId;
						log.info("找到匹配的规则：{}，匹配次数：{}，推送频率验证通过", rule.getRuleName(), matchCount);
						break;
					} else {
						errorDetails.append("规则").append(ruleId).append("(").append(rule.getRuleName()).append(")");
						errorDetails.append("匹配").append(matchCount).append("个关键字[").append(String.join(",", matchedKeywords)).append("]");
						errorDetails.append("但推送频率验证失败；");
						log.debug("规则{}的推送频率验证失败，尝试下一个规则", ruleId);
					}
				} else {
					errorDetails.append("规则").append(ruleId).append("(").append(rule.getRuleName()).append(")");
					errorDetails.append("匹配").append(matchCount).append("个关键字[").append(String.join(",", matchedKeywords)).append("]");
					errorDetails.append("但").append(validationResult.getFailureReason()).append("；");
					log.debug("规则{}的IP或域名验证失败：{}，尝试下一个规则", ruleId, validationResult.getFailureReason());
				}
			}
			
			// 4. 如果没有找到匹配的规则
			if (selectedRule == null) {
				String errorMessage = "所有规则验证失败。推送内容【" + saveDTO.getPushContent() + "】，推送IP【" + saveDTO.getPushIP() + "】，推送域名【" + saveDTO.getPushDomain() + "】。" + errorDetails.toString();
				log.warn(errorMessage);
				return errorMessage;
			}
			
			List<String> matchedKeywords = getMatchedKeywordsForRule(saveDTO.getPushContent(), selectedRuleId);
			
			String triggerCondition = buildTriggerCondition(matchedKeywords, selectedRule, saveDTO.getPushIP(), saveDTO.getPushDomain());
			
			MktMgmtPushRecord record = getMktMgmtPushRecord(saveDTO, triggerCondition, selectedRule);
			
			int result = mktMgmtPushRecordMapper.insert(record);
			if (result > 0) {
				log.info("营销推送记录新增成功，ID：{}，规则：{}，匹配关键字：{}", record.getId(), selectedRule.getRuleName(), matchedKeywords);
				return "新增成功";
			}
			
			log.warn("保存推送记录失败");
			return "保存推送记录失败";
			
		} catch (Exception e) {
			log.error("新增营销推送记录异常", e);
			return "系统异常：" + e.getMessage();
		}
	}

	/**
	 * 统计关键词
	 * @param days 统计天数
	 * @return 统计结果
	 */
	@Override
	public List<StatKeywordVO> statKeyword(Integer days) {
		log.info("开始统计关键词频率，统计天数：{}", days);

		// 计算开始时间（days天前）
		LocalDateTime startTime = LocalDateTime.now().minusDays(days);

		// 查询指定天数内的推送记录
		List<MktMgmtPushRecord> mktMgmtPushRecords = mktMgmtPushRecordMapper.selectList(
				Wrappers.<MktMgmtPushRecord>lambdaQuery()
						.ge(MktMgmtPushRecord::getCreateTime, startTime)
						.select(MktMgmtPushRecord::getTriggerCondition)
		);

		log.info("查询到{}条推送记录", mktMgmtPushRecords.size());

		// 统计关键字出现次数
		Map<String, Integer> keywordCountMap = new HashMap<>();

		for (MktMgmtPushRecord record : mktMgmtPushRecords) {
			String triggerCondition = record.getTriggerCondition();
			if (StringUtils.hasText(triggerCondition)) {
				try {
					// 解析JSON格式的triggerCondition
					JSONObject jsonObject = JSON.parseObject(triggerCondition);
					JSONArray keywordsArray = jsonObject.getJSONArray("keywords");

					if (keywordsArray != null) {
						for (int i = 0; i < keywordsArray.size(); i++) {
							String keyword = keywordsArray.getString(i);
							if (StringUtils.hasText(keyword)) {
								keywordCountMap.put(keyword, keywordCountMap.getOrDefault(keyword, 0) + 1);
							}
						}
					}
				} catch (Exception e) {
					log.warn("解析triggerCondition失败，记录ID：{}，内容：{}，错误：{}",
							record.getId(), triggerCondition, e.getMessage());
				}
			}
		}

		// 转换为StatKeywordVO列表并按出现次数降序排列
		List<StatKeywordVO> result = keywordCountMap.entrySet().stream()
				.sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
				.map(entry -> {
					StatKeywordVO vo = new StatKeywordVO();
					vo.setKeyword(entry.getKey());
					vo.setCount(entry.getValue());
					return vo;
				})
				.collect(Collectors.toList());

		log.info("统计完成，共统计到{}个不同的关键字", result.size());
		return result;
	}

	@NotNull
	private static MktMgmtPushRecord getMktMgmtPushRecord(MktMgmtPushRecordSaveDTO saveDTO, String triggerCondition, MktMgmtRule selectedRule) {
		// 构建推送详情的JSON格式
		String pushDetailJson = "{" +
				"\"triggerCondition\":" + triggerCondition +
				",\"pushContent\":\"" + selectedRule.getPushContent() + "\"" +
				",\"ruleName\":\"" + selectedRule.getRuleName() + "\"" +
				",\"pushFrequency\":" + selectedRule.getPushFrequency() +
				"}";

		MktMgmtPushRecord record = new MktMgmtPushRecord();
		record.setPushContent(selectedRule.getPushContent());
		record.setClientId(saveDTO.getClientId());
		record.setRuleName(selectedRule.getRuleName());
		record.setPushFrequency(selectedRule.getPushFrequency());
		record.setPushStatus(true); // 总为1-成功
		record.setTriggerCondition(triggerCondition);
		record.setPushDetail(pushDetailJson);
		record.setPushAction(selectedRule.getAction());
		record.setPushType(selectedRule.getPushType());
		record.setDelayPush(selectedRule.getDelayPush());
		record.setAutoPush(0);
		record.setDelFlag("0");
		return record;
	}



	
	/**
	 * IP地址转Long（便于比较大小）
	 */
	private long ipToLong(String ip) {
		String[] parts = ip.split("\\.");
		long result = 0;
		for (int i = 0; i < 4; i++) {
			result |= Long.parseLong(parts[i]) << (24 - i * 8);
		}
		return result;
	}
	
	/**
	 * 计算每条规则的关键字匹配次数
	 * 逻辑：先查询每个规则的所有关键字，然后计算每个规则中有多少个关键字能匹配到推送内容
	 */
	private Map<Long, Integer> calculateRuleMatchCounts(String pushContent) {
		if (!StringUtils.hasText(pushContent)) {
			return new HashMap<>();
		}
		
		// 1. 查询所有未删除的关键字，按规则ID分组
		LambdaQueryWrapper<MktMgmtKeyword> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(MktMgmtKeyword::getDelFlag, "0");
		queryWrapper.ne(MktMgmtKeyword::getRuleId, "0");
		List<MktMgmtKeyword> allKeywords = mktMgmtKeywordMapper.selectList(queryWrapper);
		
		// 按规则ID分组
		Map<Long, List<MktMgmtKeyword>> keywordsByRule = allKeywords.stream()
			.collect(Collectors.groupingBy(MktMgmtKeyword::getRuleId));
		
		// 2. 计算每个规则的关键字匹配次数
		Map<Long, Integer> ruleMatchCounts = new HashMap<>();
		
		for (Map.Entry<Long, List<MktMgmtKeyword>> entry : keywordsByRule.entrySet()) {
			Long ruleId = entry.getKey();
			List<MktMgmtKeyword> ruleKeywords = entry.getValue();
			
			// 计算这个规则中有多少个关键字能匹配到推送内容
			int matchCount = 0;
			for (MktMgmtKeyword keyword : ruleKeywords) {
				if (pushContent.contains(keyword.getKeyword())) {
					matchCount++;
				}
			}
			
			// 只有当匹配次数大于0时才记录
			if (matchCount > 0) {
				ruleMatchCounts.put(ruleId, matchCount);
				log.debug("规则{}的关键字匹配情况：总关键字数={}，匹配数={}", 
					ruleId, ruleKeywords.size(), matchCount);
			}
		}
		
		log.debug("规则匹配次数统计：{}", ruleMatchCounts);
		return ruleMatchCounts;
	}
	

	
	/**
	 * 获取指定规则匹配的关键字列表
	 */
	private List<String> getMatchedKeywordsForRule(String pushContent, Long ruleId) {
		if (!StringUtils.hasText(pushContent) || ruleId == null) {
			return List.of();
		}
		
		// 查询指定规则的所有关键字
		LambdaQueryWrapper<MktMgmtKeyword> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(MktMgmtKeyword::getRuleId, ruleId)
			.eq(MktMgmtKeyword::getDelFlag, "0");
		List<MktMgmtKeyword> ruleKeywords = mktMgmtKeywordMapper.selectList(queryWrapper);
		
		// 过滤匹配的关键字
		return ruleKeywords.stream()
			.map(MktMgmtKeyword::getKeyword)
			.filter(keyword -> pushContent.contains(keyword))
			.collect(Collectors.toList());
	}
	
	
	
		/**
	 * 构建触发条件描述（JSON格式）
	 */
	private String buildTriggerCondition(List<String> keywords, MktMgmtRule rule, String pushIP, String pushDomain) {
		StringBuilder json = new StringBuilder();
		json.append("{");
		json.append("\"keywords\":[").append(keywords.stream().map(k -> "\"" + k + "\"").collect(Collectors.joining(","))).append("]");
		
		// 添加IP信息
		if (StringUtils.hasText(pushIP)) {
			json.append(",\"ip\":\"").append(pushIP).append("\"");
		}
		
		// 添加域名信息
		if (StringUtils.hasText(pushDomain)) {
			json.append(",\"domain\":\"").append(pushDomain).append("\"");
		}
		
		json.append("}");
		return json.toString();
	}
	
	/**
	 * 验证结果类
	 */
	private static class ValidationResult {
		private final boolean valid;
		private final String failureReason;
		
		public ValidationResult(boolean valid, String failureReason) {
			this.valid = valid;
			this.failureReason = failureReason;
		}
		
		public boolean isValid() {
			return valid;
		}
		
		public String getFailureReason() {
			return failureReason;
		}
	}
	
	/**
	 * 验证规则的IP和域名（带详细错误信息）
	 */
	private ValidationResult validateRuleIpAndDomainWithDetails(Long ruleId, String pushIP, String pushDomain) {
		// 1. 查询规则的IP配置
		LambdaQueryWrapper<MktMgmtRuleIp> ipQueryWrapper = new LambdaQueryWrapper<>();
		ipQueryWrapper.eq(MktMgmtRuleIp::getRuleId, ruleId)
			.eq(MktMgmtRuleIp::getDelFlag, "0");
		List<MktMgmtRuleIp> ruleIps = mktMgmtRuleIpMapper.selectList(ipQueryWrapper);
		
		// 2. 查询规则的域名配置
		LambdaQueryWrapper<MktMgmtRuleDomain> domainQueryWrapper = new LambdaQueryWrapper<>();
		domainQueryWrapper.eq(MktMgmtRuleDomain::getRuleId, ruleId)
			.eq(MktMgmtRuleDomain::getDelFlag, "0");
		List<MktMgmtRuleDomain> ruleDomains = mktMgmtRuleDomainMapper.selectList(domainQueryWrapper);
		
		// 3. 如果规则没有IP和域名配置，直接通过
		if (ruleIps.isEmpty() && ruleDomains.isEmpty()) {
			return new ValidationResult(true, null);
		}
		
		// 4. 验证IP（如果有IP配置）
		if (!ruleIps.isEmpty()) {
			ValidationResult ipResult = validateRuleIpsWithDetails(ruleIps, pushIP);
			if (!ipResult.isValid()) {
				return ipResult;
			}
		}
		
		// 5. 验证域名（如果有域名配置）
		if (!ruleDomains.isEmpty()) {
			ValidationResult domainResult = validateRuleDomainsWithDetails(ruleDomains, pushDomain);
			if (!domainResult.isValid()) {
				return domainResult;
			}
		}
		
		return new ValidationResult(true, null);
	}
	
	/**
	 * 验证规则IP列表（带详细错误信息）
	 */
	private ValidationResult validateRuleIpsWithDetails(List<MktMgmtRuleIp> ruleIps, String pushIP) {
		if (!StringUtils.hasText(pushIP)) {
			return new ValidationResult(false, "推送IP为空，但规则要求IP验证");
		}
		
		for (MktMgmtRuleIp ruleIp : ruleIps) {
			ValidationResult result = validateSingleRuleIpWithDetails(ruleIp, pushIP);
			if (result.isValid()) {
				return new ValidationResult(true, null);
			}
		}
		
		return new ValidationResult(false, "推送IP " + pushIP + " 不匹配任何规则IP配置");
	}
	
	/**
	 * 验证单个规则IP（带详细错误信息）
	 */
	private ValidationResult validateSingleRuleIpWithDetails(MktMgmtRuleIp ruleIp, String pushIP) {
		if (ruleIp.getIpMode() == null) {
			return new ValidationResult(false, "规则IP配置的IP模式为空");
		}
		
		if (ruleIp.getIpMode() == 1) {
			// 单IP模式
			if (pushIP.equals(ruleIp.getStartIp())) {
				return new ValidationResult(true, null);
			} else {
				return new ValidationResult(false, "推送IP " + pushIP + " 不等于规则IP " + ruleIp.getStartIp());
			}
		} else if (ruleIp.getIpMode() == 2) {
			// IP段模式
			if (!StringUtils.hasText(ruleIp.getStartIp()) || !StringUtils.hasText(ruleIp.getEndIp())) {
				return new ValidationResult(false, "规则IP段配置不完整，起始IP或结束IP为空");
			}
			
			try {
				long pushIpLong = ipToLong(pushIP);
				long startIpLong = ipToLong(ruleIp.getStartIp());
				long endIpLong = ipToLong(ruleIp.getEndIp());
				
				if (pushIpLong >= startIpLong && pushIpLong <= endIpLong) {
					return new ValidationResult(true, null);
				} else {
					return new ValidationResult(false, "推送IP " + pushIP + " 不在IP段 " + ruleIp.getStartIp() + "-" + ruleIp.getEndIp() + " 范围内");
				}
			} catch (Exception e) {
				return new ValidationResult(false, "IP地址转换异常：" + e.getMessage());
			}
		}
		
		return new ValidationResult(false, "不支持的IP模式：" + ruleIp.getIpMode());
	}
	
	/**
	 * 验证规则域名列表（带详细错误信息）
	 */
	private ValidationResult validateRuleDomainsWithDetails(List<MktMgmtRuleDomain> ruleDomains, String pushDomain) {
		if (!StringUtils.hasText(pushDomain)) {
			return new ValidationResult(false, "推送域名为空，但规则要求域名验证");
		}
		
		for (MktMgmtRuleDomain ruleDomain : ruleDomains) {
			if (pushDomain.equals(ruleDomain.getDomain())) {
				return new ValidationResult(true, null);
			}
		}
		
		String configuredDomains = ruleDomains.stream()
			.map(MktMgmtRuleDomain::getDomain)
			.collect(Collectors.joining(", "));
		
		return new ValidationResult(false, "推送域名 " + pushDomain + " 不匹配任何规则域名配置：" + configuredDomains);
	}
	

}
