package com.hzs.system.base.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.common.core.constant.CacheConstants;
import com.hzs.common.core.constant.LanguageConstants;
import com.hzs.common.core.constant.RabbitMqConstants;
import com.hzs.common.core.enums.ELanguages;
import com.hzs.common.core.enums.EYesNo;
import com.hzs.common.core.service.RedisService;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.core.utils.OssUtil;
import com.hzs.common.core.utils.reflect.ReflectUtils;
import com.hzs.common.domain.system.base.BdTransaction;
import com.hzs.common.domain.system.base.ext.TransactionParam;
import com.hzs.common.domain.system.base.ext.TransactionResult;
import com.hzs.system.base.mapper.BdTransactionMapper;
import com.hzs.system.base.service.IBdTransactionService;
import com.hzs.third.mq.dto.TransactionMqDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileWriter;
import java.util.*;

/**
 * 统一翻译表 服务实现类
 *
 * @author hzs
 * @since 2022-08-08
 */
@Slf4j
@Service
public class BdTransactionServiceImpl extends ServiceImpl<BdTransactionMapper, BdTransaction> implements IBdTransactionService {

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisService redisService;


    /**
     * @description: 导入统一翻译信息
     * @author: zhang jing
     * @date: 2023/4/27 17:17
     * @param: [transactionList, updateSupport, userId]
     * @return: java.lang.String
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean importData(List<BdTransaction> transactionList,
                              boolean updateSupport, Long userId) {
        Date date = DateUtils.currentDate();
        for (BdTransaction bdtt : transactionList) {
            bdtt.setCreationTime(date);
            bdtt.setPkCreator(userId);
            BdTransaction bdttCheck = baseMapper.getBdTransaction(bdtt);
            if (null != bdttCheck) {
                LambdaUpdateWrapper<BdTransaction> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(BdTransaction::getChinese, bdtt.getChinese());
                updateWrapper.set(BdTransaction::getTraditional, bdtt.getTraditional());
                updateWrapper.set(BdTransaction::getEnglish, bdtt.getEnglish());
                updateWrapper.set(BdTransaction::getRussian, bdtt.getRussian());
                updateWrapper.set(BdTransaction::getKazakh, bdtt.getKazakh());
                updateWrapper.set(BdTransaction::getFrench, bdtt.getFrench());
                updateWrapper.set(BdTransaction::getModifiedTime, date);
                updateWrapper.set(BdTransaction::getPkModified, userId);
                updateWrapper.eq(BdTransaction::getKey, bdtt.getKey());
                baseMapper.update(null, updateWrapper);
            } else {
                baseMapper.insert(bdtt);
            }
        }
        return true;
    }

    @Override
    public Integer insertTransactionExt(TransactionParam transactionParam) {
        // 入库并返回
        if (baseMapper.insertTransactionExt(transactionParam) > 0) {
            // MQ异步补全其它国际化翻译
            rabbitTemplate.convertAndSend(RabbitMqConstants.TRANSLATE_EXCHANGE, RabbitMqConstants.TRANSLATE_KEY,
                    TransactionMqDTO.builder()
                            .pkId(transactionParam.getPkId())
                            .key(transactionParam.getKey() + transactionParam.getPkId())
                            .column(transactionParam.getColumn())
                            .columnValue(transactionParam.getColumnValue())
                            .isCache(transactionParam.getIsCache())
                            .build());

            return transactionParam.getPkId();
        }
        return null;
    }

    @Override
    public Integer updateTransactionExt(TransactionParam transactionParam, Boolean updateOther) {
        // 入库并返回
        if (baseMapper.updateTransactionExt(transactionParam) > 0) {
            if (null != updateOther && updateOther) {
                // MQ异步补全其它国际化翻译
                rabbitTemplate.convertAndSend(RabbitMqConstants.TRANSLATE_EXCHANGE, RabbitMqConstants.TRANSLATE_KEY,
                        TransactionMqDTO.builder()
                                .pkId(transactionParam.getPkId())
                                .key(transactionParam.getKey())
                                .column(transactionParam.getColumn())
                                .columnValue(transactionParam.getColumnValue())
                                .isCache(transactionParam.getIsCache())
                                .build());
            }
            return transactionParam.getPkId();
        }
        return null;
    }

    @Override
    public Integer initTransaction(BdTransaction bdTransaction) {
        LambdaQueryWrapper<BdTransaction> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BdTransaction::getKey, bdTransaction.getKey());
        BdTransaction transaction = baseMapper.selectOne(queryWrapper);

        if (null == transaction) {
            // 入库并返回
            if (baseMapper.insert(bdTransaction) > 0) {
                return bdTransaction.getPkId();
            }
            return null;
        }

        return transaction.getPkId();
    }

    @Override
    public String queryTransactionContent(String content, String from, String to) {
        return baseMapper.queryTransactionContent(content, from, to);
    }

    @Override
    public List<TransactionResult> queryTransactionContentList(Set<String> contentList, String from, String to) {
        return baseMapper.queryTransactionContentList(contentList, from, to);
    }

    @Override
    public TransactionResult queryTransactionKey(String key, String to) {
        return baseMapper.queryTransactionKey(key, to);
    }

    @Override
    public List<TransactionResult> queryTransactionListByKeyPrefix(Set<String> keyPrefixList, String to) {
        return baseMapper.queryTransactionListByKeyPrefix(keyPrefixList, to);
    }

    @Override
    public List<TransactionResult> queryTransactionListByPkId(Collection<Integer> pkIdList, String to) {
        return baseMapper.queryTransactionListByPkId(pkIdList, to);
    }

    @Override
    public List<BdTransaction> queryListByColumn(String column, boolean isCache, boolean isUpload) {
        return baseMapper.queryListByColumn(column, isCache, isUpload);
    }


    @Override
    public boolean initToLanguage(ELanguages eLanguages) {
        List<TransactionResult> transactionResultList = baseMapper.queryToColumnList(eLanguages.getColumn());
        if (CollectionUtil.isNotEmpty(transactionResultList)) {
            for (TransactionResult transactionResult : transactionResultList) {
                // MQ异步补全其它国际化翻译
                rabbitTemplate.convertAndSend(RabbitMqConstants.TRANSLATE_EXCHANGE, RabbitMqConstants.TRANSLATE_KEY,
                        TransactionMqDTO.builder()
                                .pkId(transactionResult.getPkId())
                                .column(ELanguages.CN.getColumn())
                                .columnValue(transactionResult.getFromContent())
                                .isCache(EYesNo.YES.getIntValue())
                                .toApiKey(eLanguages.getApiKey())
                                .build());
            }
        } else {
            log.error("{} 没有可初始化内容", eLanguages.getLabel());
        }
        return true;
    }

    @Override
    public boolean initOtherLanguage(ELanguages eLanguages, List<Long> pkIdList) {
        List<TransactionResult> transactionResultList = baseMapper.queryFromColumnList(eLanguages.getColumn(), pkIdList);
        if (CollectionUtil.isNotEmpty(transactionResultList)) {
            for (TransactionResult transactionResult : transactionResultList) {
                // MQ异步补全其它国际化翻译
                rabbitTemplate.convertAndSend(RabbitMqConstants.TRANSLATE_EXCHANGE, RabbitMqConstants.TRANSLATE_KEY,
                        TransactionMqDTO.builder()
                                .pkId(transactionResult.getPkId())
                                .column(eLanguages.getColumn())
                                .columnValue(transactionResult.getFromContent())
                                .isCache(EYesNo.YES.getIntValue())
                                .build());
            }
        } else {
            log.error("{} 没有可初始化内容", eLanguages.getLabel());
        }
        return true;
    }

    /**
     * 刷新资源
     *
     * @param languages 刷新语种（ELanguages的value）
     * @param isCache   是否刷新缓存
     * @param isOss     是否刷新OSS
     */
    @Override
    public void flushResources(Integer languages, boolean isCache, boolean isOss) {
        String column = null;
        ELanguages checkLanguages = ELanguages.getLanguagesByValue(languages);
        if (null != checkLanguages) {
            column = checkLanguages.getColumn();
        }

        // 查询需要刷新的国际化翻译
        List<BdTransaction> list = this.queryListByColumn(column, isCache, isOss);

        if (CollectionUtil.isNotEmpty(list)) {
            // 根据目前语种枚举，生成对应数据集合
            Map<String, TreeMap<String, String>> dataMap = new HashMap<>();

            if (null != column) {
                dataMap.put(checkLanguages.getLocal(), new TreeMap<>());
                // 遍历翻译列表，按语种进行封装词条
                for (BdTransaction bdTransaction : list) {
                    dataMap.get(checkLanguages.getLocal()).put(bdTransaction.getKey(), ReflectUtils.invokeGetter(bdTransaction, column));
                }
            } else {
                for (ELanguages eLanguages : ELanguages.values()) {
                    dataMap.put(eLanguages.getLocal(), new TreeMap<>());
                }
                // 遍历翻译列表，按语种进行封装词条
                for (BdTransaction bdTransaction : list) {
                    for (ELanguages eLanguages : ELanguages.values()) {
                        dataMap.get(eLanguages.getLocal()).put(bdTransaction.getKey(), ReflectUtils.invokeGetter(bdTransaction, eLanguages.getColumn()));
                    }
                }
            }
            // 刷新缓存以及OSS资源
            this.flushResourcesAll(dataMap, isCache, isOss);
        }
    }

    @Override
    public void flushResourcesAll(Map<String, TreeMap<String, String>> dataMap, boolean isCache, boolean isOss) {
        // 刷新数据，按国家进行处理
        for (String key : dataMap.keySet()) {
            if (isCache) {
                // 刷新redis缓存（先清空，再重新放入）
                redisService.deleteObject(CacheConstants.LANGUAGE_KEY + key);
                redisService.setCacheMap(CacheConstants.LANGUAGE_KEY + key, dataMap.get(key));
            }

            if (isOss) {
                // 生成web使用的js文件，并上传OSS
                FileWriter fileWriter = null;
                try {
                    File zhCnFile = File.createTempFile(LanguageConstants.WEB_RESOURCES_PREFIX, LanguageConstants.WEB_RESOURCES_SUFFIX);
                    fileWriter = new FileWriter(zhCnFile);
                    fileWriter.write("const " + key.replaceAll("-", "") + "=" + JSONUtil.toJsonStr(dataMap.get(key)));
                    fileWriter.flush();

                    OssUtil.uploadFile(zhCnFile, LanguageConstants.OSS_PATH, key + LanguageConstants.WEB_RESOURCES_SUFFIX);
                } catch (Exception e) {
                    log.error("刷新资源异常生成临时文件异常", e);
                } finally {
                    try {
                        if (null != fileWriter) {
                            fileWriter.close();
                        }
                    } catch (Exception ex) {
                        log.error("刷新资源异常关闭临时文件异常", ex);
                    }
                }
            }
        }
    }

}
