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


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pig.common.core.exception.BusinessException;
import com.pig4cloud.pig.common.core.util.ip.IPUtils;
import com.pig4cloud.pig.marketing.api.dto.rule.PageMktRuleDTO;
import com.pig4cloud.pig.marketing.api.dto.rule.SaveMktRuleDTO;
import com.pig4cloud.pig.marketing.api.entity.MktMgmtKeyword;
import com.pig4cloud.pig.marketing.api.entity.MktMgmtRule;
import com.pig4cloud.pig.marketing.api.entity.MktMgmtRuleDomain;
import com.pig4cloud.pig.marketing.api.entity.MktMgmtRuleIp;
import com.pig4cloud.pig.marketing.api.util.DomainValidationUtil;
import com.pig4cloud.pig.marketing.api.vo.rule.PageMktRuleVO;
import com.pig4cloud.pig.marketing.mapper.MktMgmtKeywordMapper;
import com.pig4cloud.pig.marketing.mapper.MktMgmtRuleDomainMapper;
import com.pig4cloud.pig.marketing.mapper.MktMgmtRuleIpMapper;
import com.pig4cloud.pig.marketing.mapper.MktMgmtRuleMapper;
import com.pig4cloud.pig.marketing.service.MktMgmtRuleService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: lwh
 * @date: 2025-08-31
 * @description: 营销管理规则Service实现类
 */
@Slf4j
@Service
@AllArgsConstructor
public class MktMgmtRuleServiceImpl implements MktMgmtRuleService {

	private final MktMgmtRuleMapper mktMgmtRuleMapper;

	private final MktMgmtKeywordMapper mktMgmtKeywordMapper;

	private final MktMgmtRuleIpMapper mktMgmtRuleIpMapper;

	private final MktMgmtRuleDomainMapper mktMgmtRuleDomainMapper;

	/**
	 * 保存/修改营销规则
	 * @param reqDto 入参
	 */
	@Override
	@Transactional
	public void saveMktRule(SaveMktRuleDTO reqDto){
		// 验证IP列表
		List<String> ipList = reqDto.getIp();
		// 验证域名列表
		List<String> domainList = reqDto.getDomain();
		// 验证关键字列表
		List<String> keywords = reqDto.getKeyword();

		// 统一验证输入数据
		if (ipList != null && !ipList.isEmpty()) {
			IPUtils.validateIpList(ipList);
		}
		if (domainList != null && !domainList.isEmpty()) {
			DomainValidationUtil.validateDomainList(domainList);
		}
		if (keywords != null && !keywords.isEmpty()) {
			validateKeywordList(keywords);
		}

		// 验证规则名
		validateRuleName(reqDto.getRuleName(), reqDto.getId());

		if (reqDto.getId() == null) {
			// 新增规则
			MktMgmtRule rule = new MktMgmtRule();
			BeanUtils.copyProperties(reqDto, rule);
			mktMgmtRuleMapper.insert(rule);

			// 保存IP列表
			if (ipList != null && !ipList.isEmpty()) {
				for (String ip : ipList) {
					if (StringUtils.hasText(ip)) {
						MktMgmtRuleIp ruleIp = buildRuleIp(ip, rule.getId());
						mktMgmtRuleIpMapper.insert(ruleIp);
					}
				}
			}

			// 保存域名列表
			if (domainList != null && !domainList.isEmpty()) {
				for (String domain : domainList) {
					if (StringUtils.hasText(domain)) {
						MktMgmtRuleDomain ruleDomain = new MktMgmtRuleDomain();
						ruleDomain.setRuleId(rule.getId());
						ruleDomain.setDomain(domain.trim());
						mktMgmtRuleDomainMapper.insert(ruleDomain);
					}
				}
			}

			// 保存关键字
			if (keywords != null && !keywords.isEmpty()) {
				for (String keyword : keywords) {
					if (StringUtils.hasText(keyword)) {
						MktMgmtKeyword mktMgmtKeyword = new MktMgmtKeyword();
						mktMgmtKeyword.setKeyword(keyword.trim());
						mktMgmtKeyword.setRuleId(rule.getId());
						mktMgmtKeywordMapper.insert(mktMgmtKeyword);
					}
				}
			}
		}
		else {
			// 修改规则
			// 1. 更新主规则信息
			MktMgmtRule mktMgmtRule = mktMgmtRuleMapper.selectById(reqDto.getId());
			if (mktMgmtRule == null) {
				throw new BusinessException("规则不存在");
			}
			MktMgmtRule rule = new MktMgmtRule();
			BeanUtils.copyProperties(reqDto, rule);
			mktMgmtRuleMapper.updateById(rule);

			Long ruleId = reqDto.getId();

			// 2. 处理IP列表
			updateIpList(ipList, ruleId);

			// 3. 处理域名列表
			updateDomainList(domainList, ruleId);

			// 4. 处理关键字列表
			updateKeywordList(keywords, ruleId);
		}
	}

	/**
	 * 删除营销规则
	 * @param ids ids
	 * @return Boolean
	 */
	@Override
	@Transactional
	public Boolean delMktRuleByIds(@ParameterObject List<Long> ids) {
		int delRule = mktMgmtRuleMapper.deleteByIds(ids);
		int delKeyword = mktMgmtKeywordMapper.delete(Wrappers.<MktMgmtKeyword>lambdaQuery()
				.in(MktMgmtKeyword::getRuleId, ids));
		int delIp = mktMgmtRuleIpMapper.delete(Wrappers.<MktMgmtRuleIp>lambdaQuery()
				.in(MktMgmtRuleIp::getRuleId, ids));
		int delDomain = mktMgmtRuleDomainMapper.delete(Wrappers.<MktMgmtRuleDomain>lambdaQuery()
				.in(MktMgmtRuleDomain::getRuleId, ids));
		return delRule > 0 && delKeyword > 0 && delIp > 0 && delDomain > 0;
	}

	/**
	 * 分页查询营销规则
	 * @param reqDto 入参
	 * @return Page
	 */
	@Override
	public Page<PageMktRuleVO> pageMktRule(PageMktRuleDTO reqDto) {
		Page<MktMgmtRule> page = new Page<>(reqDto.getCurrent(), reqDto.getSize());

		// 构建查询条件
		QueryWrapper<MktMgmtRule> queryWrapper = new QueryWrapper<>();

		// 1.1、关键字模糊查询 - 通过关联查询关键字表
		if (StringUtils.hasText(reqDto.getKeyword())) {
			// 先查询包含该关键字的规则ID
			List<MktMgmtKeyword> keywords = mktMgmtKeywordMapper.selectList(
					Wrappers.<MktMgmtKeyword>lambdaQuery()
							.like(MktMgmtKeyword::getKeyword, reqDto.getKeyword())
			);

			if (!keywords.isEmpty()) {
				List<Long> ruleIds = keywords.stream()
						.map(MktMgmtKeyword::getRuleId)
						.distinct()
						.collect(Collectors.toList());
				queryWrapper.in("id", ruleIds);
			} else {
				// 如果没有找到匹配的关键字，返回空结果
				return new Page<>();
			}
		}

		// 1.2、IP匹配逻辑 - 从IP规则表中查询
		if (StringUtils.hasText(reqDto.getIp())) {
			String inputIp = reqDto.getIp();
			// 验证输入IP格式
			if (!IPUtils.isValidIp(inputIp)) {
				throw new BusinessException("输入的IP格式不正确");
			}

			// 查询匹配IP的规则ID列表
			List<MktMgmtRuleIp> ipRules = mktMgmtRuleIpMapper.selectList(
					Wrappers.<MktMgmtRuleIp>lambdaQuery()
							.and(wrapper -> wrapper
									// 匹配单IP模式：ipMode=1 且 startIp等于输入IP
									.and(w -> w.eq(MktMgmtRuleIp::getIpMode, 1)
											.eq(MktMgmtRuleIp::getStartIp, inputIp))
									// 匹配IP段模式：ipMode=2 且 输入IP在startIp和endIp范围内
									.or(w -> w.eq(MktMgmtRuleIp::getIpMode, 2)
											.apply("INET_ATON({0}) BETWEEN INET_ATON(start_ip) AND INET_ATON(end_ip)", inputIp))
							)
			);

			if (!ipRules.isEmpty()) {
				List<Long> ruleIds = ipRules.stream()
						.map(MktMgmtRuleIp::getRuleId)
						.distinct()
						.collect(Collectors.toList());
				queryWrapper.in("id", ruleIds);
			} else {
				// 如果没有找到匹配的IP规则，返回空结果
				return new Page<>();
			}
		}

		// 1.3、域名模糊查询 - 从域名规则表中查询
		if (StringUtils.hasText(reqDto.getDomain())) {
			// 查询匹配域名的规则ID列表
			List<MktMgmtRuleDomain> domainRules = mktMgmtRuleDomainMapper.selectList(
					Wrappers.<MktMgmtRuleDomain>lambdaQuery()
							.like(MktMgmtRuleDomain::getDomain, reqDto.getDomain())
			);

			if (!domainRules.isEmpty()) {
				List<Long> ruleIds = domainRules.stream()
						.map(MktMgmtRuleDomain::getRuleId)
						.distinct()
						.collect(Collectors.toList());
				queryWrapper.in("id", ruleIds);
			} else {
				// 如果没有找到匹配的域名规则，返回空结果
				return new Page<>();
			}
		}

		// 按创建时间倒序排列
		queryWrapper.orderByDesc("create_time","id");

		// 执行分页查询
		Page<MktMgmtRule> rulePage = mktMgmtRuleMapper.selectPage(page, queryWrapper);

		// 转换为VO对象
		Page<PageMktRuleVO> resultPage = new Page<>(reqDto.getCurrent(), reqDto.getSize());
		resultPage.setTotal(rulePage.getTotal());
		resultPage.setPages(rulePage.getPages());

		List<PageMktRuleVO> voList = rulePage.getRecords().stream().map(rule -> {
			PageMktRuleVO vo = new PageMktRuleVO();
			BeanUtils.copyProperties(rule, vo);

			// 查询该规则对应的关键字列表
			List<MktMgmtKeyword> keywords = mktMgmtKeywordMapper.selectList(
					Wrappers.<MktMgmtKeyword>lambdaQuery()
							.eq(MktMgmtKeyword::getRuleId, rule.getId())
			);

			List<String> keywordList = keywords.stream()
					.map(MktMgmtKeyword::getKeyword)
					.collect(Collectors.toList());
			vo.setKeyword(keywordList);

			// 查询该规则对应的IP列表
			List<MktMgmtRuleIp> ipRules = mktMgmtRuleIpMapper.selectList(
					Wrappers.<MktMgmtRuleIp>lambdaQuery()
							.eq(MktMgmtRuleIp::getRuleId, rule.getId())
			);

			List<String> ipList = ipRules.stream().map(ipRule -> {
				if (ipRule.getIpMode() == 1) {
					// 单IP模式
					return ipRule.getStartIp();
				} else {
					// IP段模式：从endIP中提取最后一段作为后缀
					String startIp = ipRule.getStartIp();
					String endIp = ipRule.getEndIp();

					// 提取endIP的最后一段
					String[] endParts = endIp.split("\\.");
					String endSuffix = endParts[endParts.length - 1];

					return startIp + "/" + endSuffix;
				}
			}).collect(Collectors.toList());
			vo.setIp(ipList);

			// 查询该规则对应的域名列表
			List<MktMgmtRuleDomain> domainRules = mktMgmtRuleDomainMapper.selectList(
					Wrappers.<MktMgmtRuleDomain>lambdaQuery()
							.eq(MktMgmtRuleDomain::getRuleId, rule.getId())
			);

			List<String> domainList = domainRules.stream()
					.map(MktMgmtRuleDomain::getDomain)
					.collect(Collectors.toList());
			vo.setDomain(domainList);

			return vo;
		}).collect(Collectors.toList());

		resultPage.setRecords(voList);

		return resultPage;
	}

	/**
	 * 根据ID查询营销规则
	 * @param id id
	 * @return PageMktRuleVO
	 */
	@Override
	public PageMktRuleVO getMktRuleById(Long id) {
		MktMgmtRule mktMgmtRule = mktMgmtRuleMapper.selectById(id);
		if (mktMgmtRule == null){
			throw new BusinessException("规则不存在");
		}
		PageMktRuleVO result = new PageMktRuleVO();
		BeanUtils.copyProperties(mktMgmtRule, result);

		// 查询该规则对应的关键字列表
		List<MktMgmtKeyword> keywords = mktMgmtKeywordMapper.selectList(
				Wrappers.<MktMgmtKeyword>lambdaQuery()
						.eq(MktMgmtKeyword::getRuleId, id)
		);
		List<String> keywordList = keywords.stream()
				.map(MktMgmtKeyword::getKeyword)
				.collect(Collectors.toList());
		result.setKeyword(keywordList);

		// 查询该规则对应的IP列表
		List<MktMgmtRuleIp> ipRules = mktMgmtRuleIpMapper.selectList(
				Wrappers.<MktMgmtRuleIp>lambdaQuery()
						.eq(MktMgmtRuleIp::getRuleId, id)
		);

		List<String> ipList = ipRules.stream().map(ipRule -> {
			if (ipRule.getIpMode() == 1) {
				// 单IP模式
				return ipRule.getStartIp();
			} else {
				// IP段模式：从endIP中提取最后一段作为后缀
				String startIp = ipRule.getStartIp();
				String endIp = ipRule.getEndIp();

				// 提取endIP的最后一段
				String[] endParts = endIp.split("\\.");
				String endSuffix = endParts[endParts.length - 1];

				return startIp + "/" + endSuffix;
			}
		}).collect(Collectors.toList());
		result.setIp(ipList);

		// 查询该规则对应的域名列表
		List<MktMgmtRuleDomain> domainRules = mktMgmtRuleDomainMapper.selectList(
				Wrappers.<MktMgmtRuleDomain>lambdaQuery()
						.eq(MktMgmtRuleDomain::getRuleId, id)
		);

		List<String> domainList = domainRules.stream()
				.map(MktMgmtRuleDomain::getDomain)
				.collect(Collectors.toList());
		result.setDomain(domainList);

		return result;
	}

	/**
	 * 校验IP格式是否合法
	 * @param ruleIp IP信息
	 */
	private void validateIp(MktMgmtRuleIp ruleIp){
		if (!IPUtils.isValidIp(ruleIp.getStartIp())){
			throw new BusinessException("start ip 格式不合法（IPv4）");
		}
		if (ruleIp.getIpMode() == 2){
			if (!IPUtils.isValidIp(ruleIp.getEndIp())){
				throw new BusinessException("end ip 格式不合法（IPv4）");
			}
			if (!IPUtils.isEndIpGreater(ruleIp.getStartIp(), ruleIp.getEndIp())){
				throw new BusinessException("结束IP不能小于开始IP");
			}
		}
	}


	/**
	 * 验证规则名是否重复
	 * @param ruleName 规则名
	 * @param ruleId 规则ID（修改时为当前规则ID，新增时为null）
	 */
	private void validateRuleName(String ruleName, Long ruleId) {
		if (!StringUtils.hasText(ruleName)) {
			throw new BusinessException("规则名不能为空");
		}

		// 检查规则名是否已存在
		LambdaQueryWrapper<MktMgmtRule> wrapper = Wrappers.<MktMgmtRule>lambdaQuery()
				.eq(MktMgmtRule::getRuleName, ruleName.trim());

		// 如果是修改操作，排除当前规则
		if (ruleId != null) {
			wrapper.ne(MktMgmtRule::getId, ruleId);
		}

		if (mktMgmtRuleMapper.selectCount(wrapper) > 0) {
			throw new BusinessException("规则名 '" + ruleName.trim() + "' 已存在，不能重复");
		}
	}

	/**
	 * 验证关键字列表，检查重复
	 * @param keywordList 关键字列表
	 */
	private void validateKeywordList(List<String> keywordList) {
		if (keywordList == null || keywordList.isEmpty()) {
			return;
		}

		// 过滤空值，但不去重（保留重复项用于检测）
		List<String> validKeywords = keywordList.stream()
				.filter(StringUtils::hasText)
				.map(String::trim)
				.toList();

		// 检查是否有重复的关键字
		Set<String> uniqueKeywords = new HashSet<>();
		for (String keyword : validKeywords) {
			if (!uniqueKeywords.add(keyword)) {
				throw new BusinessException("关键字列表中存在重复的关键字: " + keyword);
			}
		}
	}

	/**
	 * 构建IP规则对象
	 * @param ip IP字符串
	 * @param ruleId 规则ID
	 * @return IP规则对象
	 */
	private MktMgmtRuleIp buildRuleIp(String ip, Long ruleId) {
		MktMgmtRuleIp ruleIp = new MktMgmtRuleIp();
		ruleIp.setRuleId(ruleId);

		if (ip.contains("/")) {
			// IP段格式
			String[] parts = ip.split("/");
			String startIp = parts[0];
			String endIpSuffix = parts[1];

			String[] startParts = startIp.split("\\.");
			int endSuffix = Integer.parseInt(endIpSuffix);
			String endIp = String.format("%s.%s.%s.%d",
					startParts[0], startParts[1], startParts[2], endSuffix);

			ruleIp.setIpMode(2); // IP段模式
			ruleIp.setStartIp(startIp);
			ruleIp.setEndIp(endIp);
		} else {
			// 单IP格式
			ruleIp.setIpMode(1);
			ruleIp.setStartIp(ip);
			ruleIp.setEndIp("");
		}

		// 校验IP合法性
		validateIp(ruleIp);
		return ruleIp;
	}

	/**
	 * 更新IP列表
	 * @param ipList 新IP列表
	 * @param ruleId 规则ID
	 */
	private void updateIpList(List<String> ipList, Long ruleId) {
		// 查询现有的IP记录
		List<MktMgmtRuleIp> oldIpRecords = mktMgmtRuleIpMapper.selectList(Wrappers.<MktMgmtRuleIp>lambdaQuery()
				.eq(MktMgmtRuleIp::getRuleId, ruleId));

		// 构建现有IP的映射（使用复合键：startIp + endIp + ipMode）
		Map<String, MktMgmtRuleIp> oldIpMap = oldIpRecords.stream()
				.collect(Collectors.toMap(
						ip -> ip.getStartIp() + "|" + ip.getEndIp() + "|" + ip.getIpMode(),
						ip -> ip
				));

		// 构建新IP的映射
		Map<String, MktMgmtRuleIp> newIpMap = new HashMap<>();
		if (ipList != null && !ipList.isEmpty()) {
			for (String ip : ipList) {
				if (StringUtils.hasText(ip)) {
					MktMgmtRuleIp ruleIp = buildRuleIp(ip, ruleId);
					String key = ruleIp.getStartIp() + "|" + ruleIp.getEndIp() + "|" + ruleIp.getIpMode();
					newIpMap.put(key, ruleIp);
				}
			}
		}

		// 处理需要删除的IP
		List<Long> needDeleteIpIds = oldIpRecords.stream()
				.filter(oldIp -> {
					String oldKey = oldIp.getStartIp() + "|" + oldIp.getEndIp() + "|" + oldIp.getIpMode();
					return !newIpMap.containsKey(oldKey);
				})
				.map(MktMgmtRuleIp::getId)
				.toList();
		if (!needDeleteIpIds.isEmpty()) {
			mktMgmtRuleIpMapper.deleteByIds(needDeleteIpIds);
		}

		// 处理需要新增的IP
		List<MktMgmtRuleIp> needAddIps = newIpMap.values().stream()
				.filter(newIp -> {
					String newKey = newIp.getStartIp() + "|" + newIp.getEndIp() + "|" + newIp.getIpMode();
					return !oldIpMap.containsKey(newKey);
				})
				.toList();
		if (!needAddIps.isEmpty()) {
			for (MktMgmtRuleIp ruleIp : needAddIps) {
				mktMgmtRuleIpMapper.insert(ruleIp);
			}
		}
	}

	/**
	 * 更新域名列表
	 * @param domainList 新域名列表
	 * @param ruleId 规则ID
	 */
	private void updateDomainList(List<String> domainList, Long ruleId) {
		// 查询现有的域名记录
		List<MktMgmtRuleDomain> oldDomainRecords = mktMgmtRuleDomainMapper.selectList(Wrappers.<MktMgmtRuleDomain>lambdaQuery()
				.eq(MktMgmtRuleDomain::getRuleId, ruleId));

		// 构建现有域名的映射
		Map<String, MktMgmtRuleDomain> oldDomainMap = oldDomainRecords.stream()
				.collect(Collectors.toMap(MktMgmtRuleDomain::getDomain, domain -> domain));

		// 构建新域名的映射
		Map<String, MktMgmtRuleDomain> newDomainMap = new HashMap<>();
		if (domainList != null && !domainList.isEmpty()) {
			for (String domain : domainList) {
				if (StringUtils.hasText(domain)) {
					MktMgmtRuleDomain ruleDomain = new MktMgmtRuleDomain();
					ruleDomain.setRuleId(ruleId);
					ruleDomain.setDomain(domain.trim());
					newDomainMap.put(domain.trim(), ruleDomain);
				}
			}
		}

		// 处理需要删除的域名
		List<Long> needDeleteDomainIds = oldDomainRecords.stream()
				.filter(oldDomain -> !newDomainMap.containsKey(oldDomain.getDomain()))
				.map(MktMgmtRuleDomain::getId)
				.toList();
		if (!needDeleteDomainIds.isEmpty()) {
			mktMgmtRuleDomainMapper.deleteByIds(needDeleteDomainIds);
		}

		// 处理需要新增的域名
		List<MktMgmtRuleDomain> needAddDomains = newDomainMap.values().stream()
				.filter(newDomain -> !oldDomainMap.containsKey(newDomain.getDomain()))
				.toList();
		if (!needAddDomains.isEmpty()) {
			for (MktMgmtRuleDomain ruleDomain : needAddDomains) {
				mktMgmtRuleDomainMapper.insert(ruleDomain);
			}
		}
	}

	/**
	 * 更新关键字列表
	 * @param keywords 新关键字列表
	 * @param ruleId 规则ID
	 */
	private void updateKeywordList(List<String> keywords, Long ruleId) {
		List<String> newKeywords = keywords == null ? Collections.emptyList() : keywords;

		// 查询现有的关键字记录
		List<MktMgmtKeyword> oldKeywords = mktMgmtKeywordMapper.selectList(Wrappers.<MktMgmtKeyword>lambdaQuery()
				.eq(MktMgmtKeyword::getRuleId, ruleId));
		Set<String> oldKeywordSet = oldKeywords.stream()
				.map(MktMgmtKeyword::getKeyword)
				.collect(Collectors.toSet());

		// 提取新关键字集合
		Set<String> newKeywordSet = new HashSet<>();
		for (String keyword : newKeywords) {
			if (StringUtils.hasText(keyword)) {
				newKeywordSet.add(keyword.trim());
			}
		}

		// 处理需要删除的关键字
		List<Long> needDeleteIds = oldKeywords.stream()
				.filter(keyword -> !newKeywordSet.contains(keyword.getKeyword()))
				.map(MktMgmtKeyword::getId)
				.toList();
		if (!needDeleteIds.isEmpty()) {
			mktMgmtKeywordMapper.deleteByIds(needDeleteIds);
		}

		// 处理需要新增的关键字
		List<String> needAddKeywords = newKeywordSet.stream()
				.filter(keyword -> !oldKeywordSet.contains(keyword))
				.toList();
		if (!needAddKeywords.isEmpty()) {
			for (String keyword : needAddKeywords) {
				MktMgmtKeyword mktMgmtKeyword = new MktMgmtKeyword();
				mktMgmtKeyword.setKeyword(keyword);
				mktMgmtKeyword.setRuleId(ruleId);
				mktMgmtKeywordMapper.insert(mktMgmtKeyword);
			}
		}
	}
}
