package com.ylx.massage.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylx.common.exception.ServiceException;
import com.ylx.massage.domain.SensitiveWord;
import com.ylx.massage.enums.SensitiveWordCategoryEnum;
import com.ylx.massage.mapper.SensitiveWordMapper;
import com.ylx.massage.service.SensitiveWordService;
import com.ylx.massage.utils.ExcelUtils;
import com.ylx.massage.utils.ExcelExportUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 敏感词库服务实现类
 * <p>
 * 提供敏感词管理功能的具体实现，包括敏感词的增删改查、批量导入等操作。
 * 支持从Excel文件批量导入敏感词数据，自动去重，并记录导入日志。
 * </p>
 *
 * @author ylx
 * @version 1.0
 * @since 2024
 */
@Service
public class SensitiveWordServiceImpl extends ServiceImpl<SensitiveWordMapper, SensitiveWord> implements SensitiveWordService {

    private static final Logger log = LoggerFactory.getLogger(SensitiveWordServiceImpl.class);

    @Resource
    private SensitiveWordMapper sensitiveWordMapper;

    /**
     * 批量插入敏感词数据
     *
     * @param entities 敏感词实体列表
     * @return 成功插入的记录数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertBatch(List<SensitiveWord> entities) {
        if (CollUtil.isEmpty(entities)) {
            return 0;
        }
        return sensitiveWordMapper.insertBatch(entities);
    }

    /**
     * 从Excel文件导入敏感词数据
     * <p>
     * 读取Excel文件中的敏感词数据，解析并存储到数据库中。
     * 支持的Excel格式：.xls, .xlsx
     * Excel文件格式要求：
     * - 第一行：表头（敏感词、分类、等级、状态、备注）
     * - 第二行起：数据行
     * </p>
     *
     * @param file Excel文件
     * @return 导入结果统计信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importFromExcel(MultipartFile file) {
        try {
            log.info("开始导入敏感词Excel文件，文件名：{}", file.getOriginalFilename());

            // 1. 读取Excel文件数据
            List<SensitiveWord> wordList = ExcelUtils.parseSensitiveWordExcel(file);
            log.info("Excel文件解析完成，共读取 {} 行数据", wordList.size());

            if (CollUtil.isEmpty(wordList)) {
                return "导入失败：Excel文件中没有数据";
            }

            // 2. 数据校验和去重
            List<SensitiveWord> validWords = new ArrayList<>();
            int duplicateCount = 0;
            int invalidCount = 0;

            for (SensitiveWord word : wordList) {
                // 校验敏感词
                if (StrUtil.isBlank(word.getWord())) {
                    invalidCount++;
                    continue;
                }

                // 检查是否已存在
                SensitiveWord existing = sensitiveWordMapper.selectByWord(word.getWord());
                if (existing != null) {
                    duplicateCount++;
                    continue;
                }

                // 设置默认值
                if (word.getLevel() == null) {
                    // 默认低敏感等级
                    word.setLevel(1);
                }
                if (word.getStatus() == null) {
                    // 默认启用
                    word.setStatus(1);
                }
                if (word.getIsDelete() == null) {
                    // 默认未删除
                    word.setIsDelete(0);
                }
                word.setCreateTime(new Date());
                word.setUpdateTime(new Date());
                validWords.add(word);
            }

            log.info("数据校验完成，有效数据 {} 条，重复数据 {} 条，无效数据 {} 条", validWords.size(), duplicateCount, invalidCount);

            if (CollUtil.isEmpty(validWords)) {
                return "导入失败：没有有效的数据可导入（重复或无效数据）";
            }

            // 3. 批量插入数据库
            int batchSize = 500; // 每批最多500条
            int totalInserted = 0;

            for (int i = 0; i < validWords.size(); i += batchSize) {
                int end = Math.min(i + batchSize, validWords.size());
                List<SensitiveWord> batch = validWords.subList(i, end);
                int inserted = sensitiveWordMapper.insertBatch(batch);
                totalInserted += inserted;
                log.info("已插入 {}/{} 条数据", totalInserted, validWords.size());
            }

            // 4. 返回导入结果
            String result = String.format("导入成功！共读取 %d 条数据，成功导入 %d 条，重复 %d 条，无效 %d 条", wordList.size(), totalInserted, duplicateCount, invalidCount);
            log.info(result);
            return result;
        } catch (Exception e) {
            log.error("导入敏感词Excel文件失败", e);
            throw new ServiceException("导入失败：" + e.getMessage());
        }
    }

    /**
     * 导出敏感词数据到Excel文件
     * <p>
     * 查询数据库中的所有敏感词数据（不包括已删除的记录），
     * 生成Excel文件并输出到HTTP响应流。
     * Excel文件格式：
     * - 第一行：表头（敏感词、分类、等级、状态、备注）
     * - 第二行起：数据行
     * </p>
     *
     * @param response HTTP响应对象
     */
    @Override
    public void exportToExcel(HttpServletResponse response) {
        try {
            log.info("开始导出敏感词数据到Excel");

            // 1. 查询所有敏感词数据（排除已删除）
            LambdaQueryWrapper<SensitiveWord> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.orderByAsc(SensitiveWord::getId);

            List<SensitiveWord> wordList = this.list(queryWrapper);
            log.info("查询到 {} 条敏感词数据", wordList.size());

            // 2. 生成Excel文件并写入响应流
            ExcelExportUtils.exportSensitiveWords(wordList, response);

            log.info("敏感词数据导出完成");
        } catch (IOException e) {
            log.error("导出敏感词Excel文件失败", e);
            throw new ServiceException("导出Excel文件失败：" + e.getMessage());
        }
    }
}
