package com.cmvr.tts.service.impl;

import cn.hutool.core.util.IdUtil;
import com.cmvr.common.core.minio.MinioService;
import com.cmvr.common.core.page.TableDataInfo;
import com.cmvr.common.utils.DateUtils;
import com.cmvr.common.utils.SecurityUtils;
import com.cmvr.common.utils.StringUtils;
import com.cmvr.tts.domain.CorpusCategory;
import com.cmvr.tts.domain.CorpusInfo;
import com.cmvr.tts.domain.vo.CorpusCategoryTreeVo;
import com.cmvr.tts.domain.vo.CorpusInfoVo;
import com.cmvr.tts.mapper.CorpusCategoryMapper;
import com.cmvr.tts.mapper.CorpusInfoMapper;
import com.cmvr.tts.service.ICorpusInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 车载语料数据Service业务层处理
 *
 * @author cmvr
 */
@Slf4j
@Service
public class CorpusInfoServiceImpl implements ICorpusInfoService {

    @Autowired
    private CorpusInfoMapper corpusInfoMapper;

    @Autowired
    private CorpusCategoryMapper corpusCategoryMapper;

    @Autowired
    private MinioService minioService;

    /**
     * 查询语料列表
     */
    @Override
    public TableDataInfo selectCorpusList(CorpusInfo corpus) {
        List<CorpusInfoVo> list = corpusInfoMapper.selectCorpusVoList(corpus);
        return new TableDataInfo(list, list.size());
    }

    /**
     * 新增语料
     */
    @Override
    public int insertCorpus(CorpusInfo corpus) {
        // 生成UUID作为主键
        if (corpus.getId() == null || corpus.getId().isEmpty()) {
            corpus.setId(IdUtil.fastSimpleUUID());
        }
        corpus.setCreateTime(DateUtils.getNowDate());
        corpus.setCreateBy(SecurityUtils.getUsername());
        return corpusInfoMapper.insertCorpus(corpus);
    }

    /**
     * 修改语料
     */
    @Override
    public int updateCorpus(CorpusInfo corpus) {
        corpus.setUpdateTime(DateUtils.getNowDate());
        corpus.setUpdateBy(SecurityUtils.getUsername());
        return corpusInfoMapper.updateCorpus(corpus);
    }

    /**
     * 删除语料
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteCorpusByIds(String[] ids) {
        for (String id : ids) {
            CorpusInfo corpus = corpusInfoMapper.selectCorpusById(id);
            if (corpus != null && StringUtils.isNotEmpty(corpus.getAudioFilePath())) {
                try {
                    minioService.deleteFile("cmvr-iot", corpus.getAudioFilePath());
                } catch (Exception e) {
                    log.error("删除音频文件失败: {}", corpus.getAudioFilePath(), e);
                }
            }
            corpusInfoMapper.deleteCorpusById(id);
        }
        return ids.length;
    }

    /**
     * 查询语料详情
     */
    @Override
    public CorpusInfoVo selectCorpusById(String id) {
        CorpusInfo corpus = corpusInfoMapper.selectCorpusById(id);
        if (corpus == null) {
            return null;
        }
        CorpusInfoVo vo = new CorpusInfoVo();
        BeanUtils.copyProperties(corpus, vo);
        // TODO: 补充关联查询
        return vo;
    }

    /**
     * 获取音频流
     */
    @Override
    public void getAudioStream(String corpusId, HttpServletResponse response) {
        CorpusInfo corpus = corpusInfoMapper.selectCorpusById(corpusId);
        if (corpus == null || StringUtils.isEmpty(corpus.getAudioFilePath())) {
            throw new RuntimeException("音频文件不存在");
        }
        
        try {
            InputStream inputStream = minioService.getObject("cmvr-iot", corpus.getAudioFilePath());
            response.setContentType("audio/wav");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("corpus_" + corpusId + ".wav", "UTF-8"));
            
            OutputStream outputStream = response.getOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            outputStream.flush();
            inputStream.close();
        } catch (Exception e) {
            log.error("获取音频流失败", e);
            throw new RuntimeException("获取音频流失败");
        }
    }

    /**
     * 上传语料音频
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String uploadCorpusAudio(String corpusId, MultipartFile file) {
        CorpusInfo corpus = corpusInfoMapper.selectCorpusById(corpusId);
        if (corpus == null) {
            throw new RuntimeException("语料不存在");
        }
        
        try {
            String objectName = "corpus/" + DateUtils.datePath() + "/" + corpusId + "_" + System.currentTimeMillis() + ".wav";
            minioService.upload("cmvr-iot", "corpus/" + DateUtils.datePath(), file);
            
            corpus.setAudioFilePath(objectName);
            corpus.setFileSize(file.getSize());
            corpusInfoMapper.updateCorpus(corpus);
            
            return objectName;
        } catch (Exception e) {
            log.error("上传音频失败", e);
            throw new RuntimeException("上传音频失败");
        }
    }

    /**
     * 批量导入语料
     */
    @Override
    public Map<String, Object> importCorpus(MultipartFile file) {
        Map<String, Object> result = new HashMap<>();
        result.put("successCount", 0);
        result.put("failCount", 0);
        result.put("failDetails", new ArrayList<>());
        
        // TODO: 实现Excel解析和批量导入逻辑
        
        return result;
    }

    /**
     * 导出语料
     */
    @Override
    public byte[] exportCorpusList(CorpusInfo corpus) {
        List<CorpusInfoVo> list = corpusInfoMapper.selectCorpusVoList(corpus);
        // TODO: 使用Excel工具类导出
        return new byte[0];
    }

    /**
     * 查询看板统计
     */
    @Override
    public Map<String, Object> getDashboardStats() {
        Map<String, Object> todayStats = corpusInfoMapper.selectDashboardStats();
        Map<String, Object> yesterdayStats = corpusInfoMapper.selectYesterdayStats();
        
        // 计算环比
        if (yesterdayStats != null && !yesterdayStats.isEmpty()) {
            Long todayTotal = ((Number) todayStats.get("totalCorpus")).longValue();
            Long yesterdayTotal = ((Number) yesterdayStats.get("totalCorpus")).longValue();
            todayStats.put("totalCorpusGrowth", calculatePercent(todayTotal, yesterdayTotal));
        } else {
            todayStats.put("totalCorpusGrowth", "0%");
        }
        
        return todayStats;
    }

    /**
     * 按语种统计
     */
    @Override
    public List<Map<String, Object>> getStatsByLanguage() {
        return corpusInfoMapper.selectStatsByLanguage();
    }

    /**
     * 按方言统计
     */
    @Override
    public List<Map<String, Object>> getStatsByDialect() {
        return corpusInfoMapper.selectStatsByDialect();
    }

    /**
     * 按情绪统计
     */
    @Override
    public List<Map<String, Object>> getStatsByEmotion() {
        return corpusInfoMapper.selectStatsByEmotion();
    }

    /**
     * 按分类统计
     */
    @Override
    public List<Map<String, Object>> getStatsByCategory() {
        return corpusInfoMapper.selectStatsByCategory();
    }

    /**
     * 查询分类树
     */
    @Override
    public List<CorpusCategoryTreeVo> getCategoryTree() {
        CorpusCategory queryParam = new CorpusCategory();
        List<CorpusCategory> allCategories = corpusCategoryMapper.selectList(queryParam);
        return buildCategoryTree(allCategories, "0");
    }

    /**
     * 新增分类
     */
    @Override
    public int insertCategory(CorpusCategory category) {
        category.setId(IdUtil.fastSimpleUUID());
        category.setCreateTime(DateUtils.getNowDate());
        return corpusCategoryMapper.insert(category);
    }

    /**
     * 修改分类
     */
    @Override
    public int updateCategory(CorpusCategory category) {
        category.setUpdateTime(DateUtils.getNowDate());
        return corpusCategoryMapper.updateById(category);
    }

    /**
     * 删除分类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteCategoryById(String id) {
        // 检查是否有子分类
        CorpusCategory queryParam = new CorpusCategory();
        queryParam.setParentId(id);
        List<CorpusCategory> children = corpusCategoryMapper.selectList(queryParam);
        if (children != null && !children.isEmpty()) {
            throw new RuntimeException("存在子分类，无法删除");
        }
        
        // 检查是否有关联语料
        CorpusInfo corpusParam = new CorpusInfo();
        corpusParam.setCategoryId(id);
        List<CorpusInfo> corpusList = corpusInfoMapper.selectCorpusList(corpusParam);
        if (corpusList != null && !corpusList.isEmpty()) {
            throw new RuntimeException("分类下存在语料，无法删除");
        }
        
        return corpusCategoryMapper.deleteById(id);
    }

    /**
     * 构建分类树
     */
    private List<CorpusCategoryTreeVo> buildCategoryTree(List<CorpusCategory> allCategories, String parentId) {
        return allCategories.stream()
                .filter(category -> parentId.equals(category.getParentId()))
                .map(category -> {
                    CorpusCategoryTreeVo treeVo = new CorpusCategoryTreeVo();
                    treeVo.setId(category.getId());
                    treeVo.setParentId(category.getParentId());
                    treeVo.setCategoryName(category.getCategoryName());
                    treeVo.setSortOrder(category.getSortOrder());
                    
                    List<CorpusCategoryTreeVo> children = buildCategoryTree(allCategories, category.getId());
                    if (!children.isEmpty()) {
                        treeVo.setChildren(children);
                    }
                    
                    return treeVo;
                })
                .sorted(Comparator.comparingInt(CorpusCategoryTreeVo::getSortOrder))
                .collect(Collectors.toList());
    }

    /**
     * 计算环比增长率
     */
    private String calculatePercent(Long current, Long previous) {
        if (previous == 0) {
            return current > 0 ? "+100%" : "0%";
        }
        double growth = (current - previous) * 100.0 / previous;
        return String.format("%+.2f%%", growth);
    }
}
