package com.dhcc.finance.main.service.impl;

import brave.Tracer;
import com.dhcc.common.Shift;
import com.dhcc.common.constant.SysConstants;
import com.dhcc.common.constant.SysStatusCode;
import com.dhcc.common.constant.TaStatusCode;
import com.dhcc.common.constant.enums.UsestateEnum;
import com.dhcc.common.model.CurrencyMeta;
import com.dhcc.common.model.SysUserInfo;
import com.dhcc.common.model.response.RestfulResponse;
import com.dhcc.common.util.*;
import com.dhcc.finance.main.client.VoucherTaskMonitorFeignClient;
import com.dhcc.finance.main.dao.*;
import com.dhcc.finance.main.domain.*;
import com.dhcc.finance.main.model.CwBdManualSerialWeb;
import com.dhcc.finance.main.model.CwGlVoucherImport;
import com.dhcc.finance.main.model.CwGlVoucherWeb;
import com.dhcc.finance.main.service.CwBdManualSerialService;
import com.dhcc.finance.util.MetaDataUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CwBdManualServiceImpl implements CwBdManualSerialService {

    @Autowired
    private  Tracer tracer;

    @Autowired
    private CwBdManualSerialMapper cwBdManualSerialMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private VoucherTaskMonitorFeignClient voucherTaskMonitorFeignClient;

    @Autowired
    private FinanceForThirdServiceImple financeForThirdServiceImple;

    @Autowired
    CwGlVoucherMapper cwGlVoucherMapper;//凭证信息

    @Autowired
    CwGlDetailMapper cwGlDetailMapper;//凭证分录信息

    @Autowired
    com.dhcc.finance.main.dao.CwGlFreevalueMapper CwGlFreevalueMapper;//辅助标识表

    @Autowired
    CwGlVouchermaxnoMapper cwGlVouchermaxnoMapper;//最大凭证号

    @Autowired
    CwGlBalanceMapper cwGlBalanceMapper;//辅助余额表
    @Autowired
    CwGlSettleMapper cwGlSettleMapper;// 结账信息表
    @Autowired
    CwBdGlorgbookMapper cwBdGlorgbookMapper;//账套表
    @Autowired
    CwReverseOperationMapper cwReverseOperationMapper;//反向操作
    @Autowired
    CwBdAccassitemMapper cwBdAccassitemMapper;//辅助项表
    @Autowired
    CwBdRecordSerialMapper cwBdRecordSerialMapper;//记录流水凭证表
    @Autowired
    CwBdRecordNcpushMapper cwBdRecordNcpushMapper;//记录推送nc表
    @Autowired
    PmProjectChildMapper pmProjectChildMapper;//子项目表

    @Value("${dhcc.nc.pushVoucherInterface}")
    private String pushVoucherInterface;// nc接口

    /**
     * @Description: 查询
     * @author 彭杰
     * @date 2020/6/15
     * @time
    */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestfulResponse<PageInfo<CwBdManualSerial>, CurrencyMeta> selectAll(int pageNum, int pageSize, int navigatePages, String voucherType, String importDate, String createUser) throws ParseException {
        PageHelper.startPage(pageNum, pageSize);
        List<CwBdManualSerial> list = cwBdManualSerialMapper.selectAll(voucherType, importDate, createUser);
        PageInfo<CwBdManualSerial> pageInfo = new PageInfo<>(list,navigatePages);
        return new RestfulResponse<>(SysConstants.CODE.SUCCESS, SysConstants.DEFAULT_MESSAGE.OPERATION_SUCCESS,pageInfo, MetaDataUtil.getMeta(tracer, SysStatusCode.OPERATION_SUCCESS));
    }

    /**
     * @Description: 详情
     * @author 彭杰
     * @date 2020/6/7
     * @time
    */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestfulResponse<PageInfo<CwBdManualSerial>, CurrencyMeta> selectDataDetail(int pageNum, int pageSize, int navigatePages, String batchNo, String subjcode, String projectCode, String subProjectCode, String pkVoucher) throws ParseException {
        PageHelper.startPage(pageNum, pageSize);
        List<CwBdManualSerial> list = cwBdManualSerialMapper.selectDataDetail(batchNo, subjcode, projectCode, subProjectCode, pkVoucher);
        PageInfo<CwBdManualSerial> pageInfo = new PageInfo<>(list,navigatePages);
        return new RestfulResponse<>(SysConstants.CODE.SUCCESS, SysConstants.DEFAULT_MESSAGE.OPERATION_SUCCESS,pageInfo, MetaDataUtil.getMeta(tracer, SysStatusCode.OPERATION_SUCCESS));
    }

    /**
     * @Description: 导入且查看凭证
     * @author 彭杰
     * @date 2020/6/10
     * @time
    */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public RestfulResponse<Object, CurrencyMeta> importBatchReportInfo(MultipartFile file) {
        SysUserInfo sysUserInfo = CacheDataUtil.<SysUserInfo>getCacheBean(stringRedisTemplate,
                SysConstants.REDIS_KEY_PREFIX.SYS_USER_INFO, SysUserInfo.class);
        // 是否获取到登录用户缓存信息
        if (sysUserInfo == null) {
            return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,
                    SysConstants.DEFAULT_MESSAGE.OPERATION_FAIL,
                    MetaDataUtil.getMeta(tracer, SysStatusCode.OPERATION_FAIL));
        }
        List<CwBdManualSerialWeb> importList = new ArrayList<>();
        XSSFWorkbook wb = null;
        // 获取上传文件
        File[] files = null;
        Sheet sheet ;
        try {
            files = FileUtil.multipartFileTransferToFile(file);
            // 读取excel文件
            for (File file2 : files) {
                FileInputStream fs = FileUtils.openInputStream(file2);
                wb = new XSSFWorkbook(fs);
                sheet = wb.getSheetAt(0);
                // 读取excel文件
                importList = ExcelUtils.readData(sheet,CwBdManualSerialWeb.class,1,10000);
            }
            if (importList == null || importList.size() <= 0){
                return new RestfulResponse<>(SysConstants.CODE.FAIL,
                        SysConstants.BASIC_JDBC_RES_MESSAGE.SAVE_FAIL,
                        MetaDataUtil.getMeta(tracer, SysStatusCode.OPERATION_FAIL));
            }
        } catch (Exception e) {
            String errorMessage = " 读取导入文件出错";
            log.error(errorMessage,e);
        }
        if(CollectionUtils.isNotEmpty(importList)) {
            // 获取所有的字典信息
            Map<String, Map<String, String>> conversionDict = conversionDict(CwBdManualSerialWeb.class);
            for (CwBdManualSerialWeb isir : importList) {
                isir.setVoucherType(conversionDict.get("生成凭证类型").get(isir.getVoucherType()));// 凭证类型
            }
        }
        return new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.SUCCESS,SysConstants.BASIC_JDBC_RES_MESSAGE.SAVE_SUCCESS,importList,MetaDataUtil.getMeta(tracer, SysStatusCode.OPERATION_SUCCESS));
    }

    /**
     * @Description: 保存导入的文件信息
     * @author 彭杰
     * @date 2020/6/11
     * @time
    */
    @Override
    public RestfulResponse<Object, CurrencyMeta> importBatchVoucherInfo(List<CwBdManualSerialWeb> list) {
        //是否获取到当前用户缓存信息
        if (list == null || list.size() <= 0)
            return new RestfulResponse<>(SysConstants.CODE.FAIL,
                    SysConstants.BASIC_JDBC_RES_MESSAGE.SAVE_FAIL,
                    MetaDataUtil.getMeta(tracer, SysStatusCode.OPERATION_FAIL));
        SysUserInfo sysUserInfo = CacheDataUtil.<SysUserInfo>getCacheBean(stringRedisTemplate,
                SysConstants.REDIS_KEY_PREFIX.SYS_USER_INFO, SysUserInfo.class);
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String sid = SnowflakeIdWorker.getInstance().nextIdString();
        List<CwGlVoucherImport> arList = new ArrayList<>();
        list.forEach(data -> {
            if (sysUserInfo != null) {
                CwGlVoucherImport cwGlVoucherImport = new CwGlVoucherImport();
                //保存到cwbdmanualserial表
                data.setId(SnowflakeIdWorker.getInstance().nextIdString());
                data.setBatchNo(sid);
                data.setUseState(UsestateEnum.EFFECTIVE.getCodeStr());
                data.setCreateUser(sysUserInfo.getUserId());

                cwGlVoucherImport.setTradeCode("CJ1033");
                cwGlVoucherImport.setTempType(data.getVoucherType());
                cwGlVoucherImport.setBatchNo(sid);
                arList.add(cwGlVoucherImport);

                try {
                    data.setImportDate(sdf2.parse(sdf2.format(date)));
                    data.setCreateTime(sdf1.parse(sdf1.format(date)));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        });
        List<CwGlVoucherImport> arlist = arList.stream().distinct().collect(Collectors.toList());
        int i = cwBdManualSerialMapper.importBatchVoucherInfo(list);
        if (i <= 0) {
            return new RestfulResponse<>(SysConstants.CODE.FAIL,
                    SysConstants.BASIC_JDBC_RES_MESSAGE.SAVE_FAIL,
                    MetaDataUtil.getMeta(tracer, SysStatusCode.OPERATION_FAIL));
        }
        System.out.println("传递值："+arlist.toString());
        //调用生成凭证接口
        financeForThirdServiceImple.addCwGlVoucherBatch(arlist);

        return new RestfulResponse<>(SysConstants.CODE.SUCCESS,
                SysConstants.BASIC_JDBC_RES_MESSAGE.SAVE_SUCCESS, i,
                MetaDataUtil.getMeta(tracer, SysStatusCode.OPERATION_SUCCESS));
    }

    //删除查看列表信息（未用）
    @Override
    public RestfulResponse<Object, CurrencyMeta> deleteImportReportInfo() {
        cwBdManualSerialMapper.deleteByExample(new CwBdManualSerialExample());
        return new RestfulResponse<>(SysConstants.CODE.SUCCESS,
                SysConstants.BASIC_JDBC_RES_MESSAGE.SAVE_SUCCESS,
                MetaDataUtil.getMeta(tracer, SysStatusCode.OPERATION_SUCCESS));
    }

    //查询凭证详情
    @Override
    public RestfulResponse<CwGlVoucherWeb, CurrencyMeta> selectPLVoucherDetil(String pkVoucher, String useState){
        CwGlVoucherWeb cwGlVoucherWeb = cwGlVoucherMapper.selectOrderMakingDetil(pkVoucher, useState);
        List<CwGlDetail> selectByPkVoucher = cwGlDetailMapper.selectByPkVoucher(pkVoucher, useState);
        // 对摘要重新赋值
        if (cwGlVoucherWeb != null) {
            cwGlVoucherWeb.getCwGlDetailList().forEach(x -> {
                // 对摘要重新赋值
                for (CwGlDetail cwGlDetail : selectByPkVoucher) {
                    if (x.getPkDetail().equals(cwGlDetail.getPkDetail())) {
                        x.setAbstracts(cwGlDetail.getAbstracts());
                    }
                }
                // 辅助项转中文名(不用转了)
                if (x.getCwGlFreevalueList() != null && !x.getCwGlFreevalueList().isEmpty() && StringUtils.isNotBlank(x.getAssid())) {

                } else {
                    x.setCwGlFreevalueList(new ArrayList<CwGlFreevalue>());
                }
            });
        }
        return new RestfulResponse<CwGlVoucherWeb, CurrencyMeta>(SysConstants.CODE.SUCCESS,
                SysConstants.DEFAULT_MESSAGE.OPERATION_SUCCESS, cwGlVoucherWeb, MetaDataUtil.getMeta(tracer, SysStatusCode.OPERATION_SUCCESS));
    }

    /**
     * @Description: 字典名数据字典转化字典项
     * @author 彭杰
     * @date 2020/6/10
     * @time
    */
    private <T> Map<String, Map<String, String>> conversionDict(Class<T> cls) {
        List<String> list = new ArrayList<String>();
        Map<String, Map<String, String>> map = new HashMap<String, Map<String, String>>();
        Field[] fields = cls.getDeclaredFields();// 获取类的所有字段
        for (Field field : fields) {
            ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
            if (annotation != null && ((annotation.col() > 0)) && annotation.key() != "") {
                list.add(annotation.key());
            }
        }
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String str = iterator.next();
            if (str.equals("")) {
                iterator.remove();
            }
        }
        // 查询所有字典
        RestfulResponse<List<SysDictInfo>, CurrencyMeta> response = voucherTaskMonitorFeignClient.searchDictInfoByDictName(list);
        if (response.getCode() == 1 && response.getData() != null) {
            for (Field field : fields) {
                ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                Map<String, String> map1 = new HashMap<String, String>();
                Map<String, String> map2 = new HashMap<String, String>();
                if (annotation != null && ((annotation.col() > 0)) && !annotation.key().equals("")) {
                    for (int i = 0; i < response.getData().size(); i++) {
                        if (response.getData().get(i).getDictField().equals(annotation.key())) {
                            map1.put(response.getData().get(i).getDictKey(), response.getData().get(i).getDictValue());
                            map2.put(response.getData().get(i).getDictValue(), response.getData().get(i).getDictKey());
                        }

                    }
                    map.put(annotation.key(), map1);
                    map.put(annotation.value(), map2);
                }
            }
        } else {
            Shift.fatalThrow(TaStatusCode.DO_EXPORT_FAIL);
        }
        return map;
    }

}
