package com.artfess.cqlt.manager.impl;

import com.alibaba.fastjson.JSONObject;
import com.artfess.base.exception.BaseException;
import com.artfess.base.manager.impl.BaseManagerImpl;
import com.artfess.base.util.BeanUtils;
import com.artfess.cqlt.dao.QfFinanceReportingSummaryMDao;
import com.artfess.cqlt.manager.QfEnterpriseInfoManager;
import com.artfess.cqlt.manager.QfFinanceReportingSummaryDManager;
import com.artfess.cqlt.manager.QfFinanceReportingSummaryMManager;
import com.artfess.cqlt.manager.QfFinanceReportingSummarySManager;
import com.artfess.cqlt.model.QfEnterpriseInfo;
import com.artfess.cqlt.model.QfFinanceReportingSummaryD;
import com.artfess.cqlt.model.QfFinanceReportingSummaryM;
import com.artfess.cqlt.model.QfFinanceReportingSummaryS;
import com.artfess.i18n.util.I18nUtil;
import com.artfess.poi.util.HeaderNode;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * 财务-国资委资产负债和利润填报主表 服务实现类
 *
 * @company 阿特菲斯信息技术有限公司
 * @author min.wu
 * @since 2023-03-06
 */
@Slf4j
@Service
public class QfFinanceReportingSummaryMManagerImpl extends BaseManagerImpl<QfFinanceReportingSummaryMDao, QfFinanceReportingSummaryM> implements QfFinanceReportingSummaryMManager {

    @Autowired
    private QfFinanceReportingSummaryDManager financeReportingSummaryDManager;

    @Autowired
    private QfFinanceReportingSummarySManager financeReportingSummarySManager;

    @Autowired
    private QfEnterpriseInfoManager enterpriseInfoManager;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(QfFinanceReportingSummaryM t) {
        QfFinanceReportingSummaryM QfFinanceReportingSummaryM = baseMapper.selectById(t.getId());
        if (null == QfFinanceReportingSummaryM) {
            return false;
        }
        QfFinanceReportingSummaryM.setStatus(QfFinanceReportingSummaryM.getStatus() == 0 ? 1 : 0);
        int i = this.baseMapper.updateById(QfFinanceReportingSummaryM);
        if (i > 0) {
            return true;
        }
        return false;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean importExcel(List<HeaderNode> list, String mainId) {
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        QfFinanceReportingSummaryM mainInfo = this.baseMapper.selectById(mainId);
        Assert.notNull(mainInfo, I18nUtil.getMessage("filldata.notExist", LocaleContextHolder.getLocale()));
        Assert.isTrue(!"1".equals(mainInfo.getStatus()),  I18nUtil.getMessage("data_operate", LocaleContextHolder.getLocale()));

        //获取境外企业
        Map<String, QfEnterpriseInfo> enterpriseInfoMap = enterpriseInfoManager.getEnterpriseInfoMap(null);

        List<HeaderNode> headerNodeList = list.stream().collect(Collectors.groupingBy(HeaderNode::getRow)).get(0);
        Map<Integer, String> headerMap = Maps.newHashMap();
        for (HeaderNode headerNode : headerNodeList) {
            headerMap.put(headerNode.getColumn(), headerNode.getHeaderName());
        }

        //获取科目所在行 以及科目编码信息
        Map<Integer, List<HeaderNode>> detailMap = list.stream().collect(Collectors.groupingBy(HeaderNode::getColumn));
        List<HeaderNode> subjectCodes = detailMap.get(1);
        Map<Integer, String> subjectCodeMap = Maps.newHashMap();
        for (HeaderNode headerNode : subjectCodes) {
            subjectCodeMap.put(headerNode.getRow(), headerNode.getHeaderName());
        }

        List<HeaderNode> subjectNameEns = detailMap.get(0);
        Map<Integer, String> subjectNameEnsMap = Maps.newHashMap();
        for (HeaderNode headerNode : subjectNameEns) {
            subjectNameEnsMap.put(headerNode.getRow(), headerNode.getHeaderName());
        }
        int maxColumn = detailMap.size();
        List<QfFinanceReportingSummaryD> detailList = Lists.newArrayList();
        JSONObject totalInfo = new JSONObject();
        for (Map.Entry<Integer, List<HeaderNode>> entry : detailMap.entrySet()) {
            Integer column = entry.getKey();
            List<HeaderNode> nodes = entry.getValue();
            //获取企业编码
            String enterpriseCode = headerMap.get(column);

            for (HeaderNode node : nodes) {
                if (0 == node.getRow()) {
                    continue;
                }
                String subjectCode = subjectCodeMap.get(node.getRow());
                if (node.getColumn() > 1 && node.getColumn() < maxColumn - 3 && !StringUtils.isEmpty(node.getHeaderName())) {
                    createDetail(mainInfo, enterpriseInfoMap, subjectCodeMap, subjectNameEnsMap,detailList, enterpriseCode, node);
                } else if (node.getColumn() >= maxColumn - 3 && !StringUtils.isEmpty(node.getHeaderName())) {
                    if (node.getColumn() == maxColumn - 1) {
                        totalInfo.put(subjectCode + ":actualConsolidated", node.getHeaderName());
                    } else if (node.getColumn() == maxColumn - 2) {
                        totalInfo.put(subjectCode + ":actualPosting", node.getHeaderName());
                    } else if (node.getColumn() == maxColumn - 3) {
                        totalInfo.put(subjectCode + ":actualTotal", node.getHeaderName());
                    }
                }

            }
        }

        List<QfFinanceReportingSummaryS> totalList = createTotalInfo(mainInfo, subjectCodeMap, subjectNameEnsMap, totalInfo);
        financeReportingSummarySManager.saveBatch(totalList);
        try {
            partitionSave(detailList);
        } catch (Exception e) {
            log.error("导入例如报表数据失败:{}", e.getMessage());
            return false;
        }

        return true;
    }

    private List<QfFinanceReportingSummaryS> createTotalInfo(QfFinanceReportingSummaryM mainInfo,
                                                             Map<Integer, String> subjectCodeMap,
                                                             Map<Integer, String> subjectNameEnsMap, JSONObject totalInfo) {
        List<QfFinanceReportingSummaryS> totalList = Lists.newArrayList();
        subjectCodeMap.forEach((row, subjectCode) -> {
            QfFinanceReportingSummaryS summaryS = new QfFinanceReportingSummaryS();
            summaryS.setMainId(mainInfo.getId());
            //处理课目
            summaryS.setSubjectNameEn(subjectNameEnsMap.get(row));
            summaryS.setSubjectUnit("欧元");
            summaryS.setSubjectCode(subjectCode);
            if (totalInfo.containsKey(subjectCode + ":actualConsolidated")) {
                summaryS.setActualConsolidated(totalInfo.getBigDecimal(subjectCode + ":actualConsolidated"));
            }
            if (totalInfo.containsKey(subjectCode + ":actualPosting")) {
                summaryS.setActualPosting(totalInfo.getBigDecimal(subjectCode + ":actualPosting"));
            }
            if (totalInfo.containsKey(subjectCode + ":actualTotal")) {
                summaryS.setActualTotal(totalInfo.getBigDecimal(subjectCode + ":actualTotal"));
            }
            summaryS.setFillYear(mainInfo.getFillYear());
            summaryS.setFillMonth(mainInfo.getFillMonth());
            summaryS.setFillDate(mainInfo.getFillDate());
            summaryS.setFillQuarter(mainInfo.getFillQuarter());
            summaryS.setSubjectCode(subjectCode);
            totalList.add(summaryS);

        });
        return totalList;
    }

    private void partitionSave(List<QfFinanceReportingSummaryD> detailList) throws InterruptedException {
        List<List<QfFinanceReportingSummaryD>> partition = BeanUtils.partition(detailList, detailList.size()/10);
        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(partition.size());
        // 声明线程计数器 记录单个任务的执行次数
        CountDownLatch countDownLatch = new CountDownLatch(partition.size());
        // 遍历处理拆分的list数据
        for (int i = 0; i < partition.size(); i++) {
            int finalI = i;
            executorService.execute(() -> {
                // 业务处理部分
                List<QfFinanceReportingSummaryD> importParamDTOList = partition.get(finalI);
                financeReportingSummaryDManager.saveOrUpdateBatch(importParamDTOList);
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        //关闭线程池
        executorService.shutdown();
    }

    private void createDetail(QfFinanceReportingSummaryM mainInfo,
                              Map<String, QfEnterpriseInfo> enterpriseInfoMap,
                               Map<Integer, String> subjectCodeMap,
                              Map<Integer, String> subjectNameEnsMap,
                              List<QfFinanceReportingSummaryD> detailList,
                              String enterpriseCode,
                              HeaderNode node) {
        QfFinanceReportingSummaryD detail = new QfFinanceReportingSummaryD();
        detail.setMainId(mainInfo.getId());
        detail.setSn(node.getRow());
        detail.setColumn(node.getColumn());
        detail.setFillDate(mainInfo.getFillDate());
        detail.setEnterpriseCode(enterpriseCode);
        detail.setSubjectCode(subjectCodeMap.get(node.getRow()));
        detail.setSubjectNameEn(subjectNameEnsMap.get(node.getRow()));
        detail.setActualYtd(new BigDecimal(node.getHeaderName()));
        //处理企业
        if (enterpriseInfoMap.containsKey(detail.getEnterpriseCode())) {
            QfEnterpriseInfo qfEnterpriseInfo = enterpriseInfoMap.get(detail.getEnterpriseCode());
            detail.setEnterpriseName(qfEnterpriseInfo.getName());
            detail.setEnterpriseNameEn(qfEnterpriseInfo.getNameEn());
        }
        detailList.add(detail);
    }

    public void removeInfo(String mainId) {
        QueryWrapper<QfFinanceReportingSummaryD> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("main_id_", mainId);
        financeReportingSummaryDManager.remove(queryWrapper);

        QueryWrapper<QfFinanceReportingSummaryS> query = new QueryWrapper<>();
        query.eq("main_id_", mainId);
        financeReportingSummarySManager.remove(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertInfo(QfFinanceReportingSummaryM t) {
        QueryWrapper<QfFinanceReportingSummaryM> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("fill_year_", t.getFillYear());
        queryWrapper.eq("fill_month_", t.getFillMonth());
        queryWrapper.eq("report_id_", t.getReportId());
        List<QfFinanceReportingSummaryM> QfFinanceReportingSummaryMS = this.baseMapper.selectList(queryWrapper);
        if (!CollectionUtils.isEmpty(QfFinanceReportingSummaryMS)) {
            throw new BaseException(I18nUtil.getMessage("QfOperationKpiM.repeat", LocaleContextHolder.getLocale()));
        }
        int insert = this.baseMapper.insert(t);
        if (insert > 0) {
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateInfo(QfFinanceReportingSummaryM t) {
        QueryWrapper<QfFinanceReportingSummaryM> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("fill_year_", t.getFillYear());
        queryWrapper.eq("fill_month_", t.getFillMonth());
        queryWrapper.eq("report_id_", t.getReportId());
        queryWrapper.ne("id_", t.getId());
        List<QfFinanceReportingSummaryM> QfFinanceReportingSummaryMS = this.baseMapper.selectList(queryWrapper);
        if (!CollectionUtils.isEmpty(QfFinanceReportingSummaryMS)) {
            throw new BaseException(I18nUtil.getMessage("QfOperationKpiM.repeat", LocaleContextHolder.getLocale()));
        }
        int insert = this.baseMapper.updateById(t);
        if (insert > 0) {
            return true;
        }
        return false;
    }
}
