package com.tangguo.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.common.core.redis.RedisCache;
import com.tangguo.common.exception.ServiceException;
import com.tangguo.common.utils.SensitiveWordUtils;
import com.tangguo.common.utils.StringUtils;
import com.tangguo.domain.BbsSensitiveWord;
import com.tangguo.domain.DataImportResult;
import com.tangguo.mapper.BbsSensitiveWordMapper;
import com.tangguo.service.IBbsSensitiveWordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;

/**
 * 敏感词库Service业务层处理
 *
 * @author ruoyi
 * @date 2025-08-27
 */
@Slf4j
@Service
public class BbsSensitiveWordServiceImpl extends ServiceImpl<BbsSensitiveWordMapper, BbsSensitiveWord> implements IBbsSensitiveWordService {

	private static final String WORD_CACHE_KEY = "sensitive:words";

	@Resource
	private BbsSensitiveWordMapper bbsSensitiveWordMapper;

	@Resource
	private RedisCache redisCache;


	@PostConstruct
	private void initCacheWords() {
		Set<String> dbWords = this.getDbWords();
		SensitiveWordUtils.addWords(dbWords);
		log.info("=> 数据库敏感词已缓存，敏感词数量：{}", dbWords.size());
	}


	/**
	 * 查询敏感词
	 *
	 * @return 敏感词
	 */
	@Override
	public Set<String> getDbWords() {
		List<String> dbWords = this.listObjs(
			Wrappers.lambdaQuery(BbsSensitiveWord.class).select(BbsSensitiveWord::getName), Objects::toString
		);
		return new HashSet<>(dbWords);
	}


	/**
	 * 重新加载缓存敏感词
	 */
	@Override
	public void reloadCacheWords() {
		Set<String> dbWords = this.getDbWords();
		SensitiveWordUtils.reloadWords(dbWords);
	}


	/**
	 * 查询敏感词库列表
	 *
	 * @param word 敏感词库
	 * @return 敏感词库
	 */
	@Override
	public List<BbsSensitiveWord> selectBbsSensitiveWordList(BbsSensitiveWord word) {
		LambdaQueryWrapper<BbsSensitiveWord> lqw = Wrappers.lambdaQuery();
		lqw.orderByDesc(BbsSensitiveWord::getCreateTime);
		lqw.like(StringUtils.isNotBlank(word.getName()), BbsSensitiveWord::getName, word.getName());
		return bbsSensitiveWordMapper.selectList(lqw);
	}


	/**
	 * 新增敏感词
	 *
	 * @param word 敏感词
	 */
	@Override
	public void addWord(BbsSensitiveWord word) {
		long wordCount = this.count(
			Wrappers.lambdaQuery(BbsSensitiveWord.class).eq(BbsSensitiveWord::getName, word.getName())
		);
		if (wordCount > 0) {
			throw new ServiceException("添加失败，当前敏感词已存在。");
		}

		BbsSensitiveWord addWord = new BbsSensitiveWord();
		addWord.setName(word.getName());
		addWord.setSort(word.getSort());
		addWord.setEnableStatus(1);
		this.save(addWord);
		SensitiveWordUtils.addWords(addWord.getName());
	}


	/**
	 * 修改敏感词
	 *
	 * @param word 敏感词
	 */
	@Override
	public void editWord(BbsSensitiveWord word) {
		BbsSensitiveWord dbWord = this.getById(word.getId());
		if (Objects.isNull(dbWord)) {
			throw new ServiceException("修改失败，未查询到当前敏感词数据。");
		}

		if (!dbWord.getName().equals(word.getName())) {
			long wordCount = this.count(
				Wrappers.lambdaQuery(BbsSensitiveWord.class).eq(BbsSensitiveWord::getName, word.getName())
			);
			if (wordCount > 0) {
				throw new ServiceException("修改失败，当前敏感词已存在。");
			}
		}

		BbsSensitiveWord updWord = new BbsSensitiveWord();
		updWord.setId(dbWord.getId());
		updWord.setName(word.getName());
		updWord.setSort(word.getSort());
		this.updateById(updWord);
		this.reloadCacheWords();
	}


	/**
	 * 删除敏感词
	 *
	 * @param wordId 敏感词Id
	 */
	@Override
	public void deleteWord(Long wordId) {
		BbsSensitiveWord dbWord = this.getById(wordId);
		if (Objects.nonNull(dbWord)) {
			this.removeById(wordId);
			this.reloadCacheWords();
		}
	}


	/**
	 * 导入敏感词
	 *
	 * @param file 铭感词文件
	 * @return 导入结果
	 */
	@Override
	public DataImportResult<String> importWords(MultipartFile file) {
		DataImportResult<String> result = new DataImportResult<>();
		BufferedReader reader = null;
		try {
			// 读取敏感词
			reader = new BufferedReader(new InputStreamReader(file.getInputStream()));
			String readWord;
			Set<String> readWords = new LinkedHashSet<>(10);
			while (Objects.nonNull(readWord = reader.readLine())) {
				if (StrUtil.isNotBlank(readWord)) {
					readWords.add(readWord);
				}
			}

			// 校验敏感词
			Set<String> cacheWords = this.redisCache.getCacheSet(WORD_CACHE_KEY);
			List<BbsSensitiveWord> addWords = new ArrayList<>(readWords.size());
			for (String word : readWords) {
				if (!cacheWords.contains(word)) {
					BbsSensitiveWord newWord = new BbsSensitiveWord();
					newWord.setName(word);
					addWords.add(newWord);
				} else {
					DataImportResult.Row<String> row = new DataImportResult.Row<>();
					row.setRowData(word);
					row.setMessage("当前敏感词已存在");
					result.getFailRows().add(row);
				}
			}
			super.saveBatch(addWords);

			// 缓存敏感词
			this.redisCache.setAddValues(WORD_CACHE_KEY, addWords.toArray());

			result.setTotalCount(readWords.size());
			result.setSuccessCount(addWords.size());
			result.setFailCount(readWords.size() - addWords.size());

		} catch (Exception e) {
			log.error("=> 导入敏感词失败：", e);
		} finally {
			IoUtil.close(reader);
		}
		return result;
	}

}
