package pwc.taxtech.atms.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.*;

import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import pwc.taxtech.atms.analysis.dao.*;
import pwc.taxtech.atms.analysis.entity.*;
import pwc.taxtech.atms.common.util.DateUtils;
import pwc.taxtech.atms.constant.enums.EnumTbImportType;
import pwc.taxtech.atms.dao.*;
import pwc.taxtech.atms.dpo.AnalysisSalesValueDto;
import pwc.taxtech.atms.dpo.ProjectAnaylsisDto;
import pwc.taxtech.atms.entity.*;
import pwc.taxtech.atms.vat.dao.PeriodCellDataMapper;
import pwc.taxtech.atms.vat.dao.ProfitLossStatementFinalMapper;
import pwc.taxtech.atms.vat.dao.TrialBalanceFinalMapper;
import pwc.taxtech.atms.vat.entity.ProfitLossStatement;
import pwc.taxtech.atms.vat.entity.ProfitLossStatementExample;
import pwc.taxtech.atms.vat.entity.TrialBalanceFinal;
import pwc.taxtech.atms.vat.entity.TrialBalanceFinalExample;

import javax.annotation.Resource;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Auther: Gary J Li
 * @Date: 19/03/2019 15:52
 * @Description:
 */
@Service
public class AnalysisJobServiceImpl extends BaseService {

    @Resource
    private AnalysisDriverNumMapper analysisDriverNumMapper;
    @Resource
    private AnalysisEmployeeNumMapper analysisEmployeeNumMapper;
    @Resource
    private AnalysisExpectedTaxReturnMapper analysisExpectedTaxReturnMapper;
    @Resource
    private AnalysisActualTaxReturnMapper analysisActualTaxReturnMapper;
    @Resource
    private AnalysisFeeMapper analysisFeeMapper;
    @Resource
    private AnalysisFileManagementMapper analysisFileManagementMapper;
    @Resource
    private AnalysisGmvSubsidyMapper analysisGmvSubsidyMapper;
    @Resource
    private AnalysisInternationalBusinessDataMapper analysisInternationalBusinessDataMapper;
    @Resource
    private AnalysisInternationalTaxDataMapper analysisInternationalTaxDataMapper;
    @Resource
    private AnalysisMasterMapper analysisMasterMapper;
    @Resource
    private AnalysisSalesMapper analysisSalesMapper;
    @Resource
    private AnalysisTaxMapper analysisTaxMapper;
    @Resource
    private AnalysisTaxReturnEndMapper analysisTaxReturnEndMapper;
    @Resource
    private OrganizationAccountingRateMapper accountingRateMapper;
    @Resource
    private OrganizationReturnRateMapper organizationReturnRateMapper;
    @Resource
    private AreaMapper areaMapper;
    @Resource
    private RegionMapper regionMapper;
    @Resource
    private BusinessUnitMapper businessUnitMapper;
    @Resource
    private TrialBalanceFinalMapper trialBalanceFinalMapper;
    @Resource
    private PeriodCellDataMapper periodCellDataMapper;
    @Resource
    private ProfitLossStatementFinalMapper profitLossStatementFinalMapper;
    @Resource
    private ProjectMapper projectMapper;
    @Resource
    private TaxDocumentMapper taxDocumentMapper;
    @Resource
    private OrganizationTaxRuleMapper organizationTaxRuleMapper;

    private final static List<Integer> MONTH_LIST = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);

    private final static List<Integer> Q_LIST = Lists.newArrayList(3, 6, 9, 12);


    /**
     * 19/03/2019 15:55
     * admin中获取
     * 汇率 select rate from organization_accounting_rate currency_from(org.currency_code) and currency_to='CNY'
     * [orgs,period]
     *
     * @return
     * @author Gary J Li
     */
    public void analysisMaster(List<Organization> orgs, Integer period,Integer type) {
        List<String> orgIds = orgs.stream().map(Organization::getId).collect(Collectors.toList());
        if(type.equals(EnumTbImportType.CoverImport.getCode())){
            AnalysisMasterExample example = new AnalysisMasterExample();
            example.createCriteria().andOrganizationIdIn(orgIds).andPeriodEqualTo(period);
            analysisMasterMapper.deleteByExample(example);
        }
        OrganizationExample e1 = new OrganizationExample();
        e1.createCriteria().andIsActiveEqualTo(true);

        List<String> currencys = orgs.stream().map(Organization::getCurrencyCode).collect(Collectors.toList());

        OrganizationAccountingRateExample e2 = new OrganizationAccountingRateExample();
        e2.createCriteria().andCurrencyFromIn(currencys).andCurrencyToEqualTo("CNY");
        List<OrganizationAccountingRate> rates = accountingRateMapper.selectByExample(e2);
        List<Area> areas = areaMapper.selectTopAreas();
        Map<String, String> areaMap = new HashMap<>();
        areas.forEach(a -> {
            areaMap.put(a.getId(), a.getName());
        });

        List<Region> regions = regionMapper.selectByExample(new RegionExample());
        Map<String, String> regionMap = new HashMap<>();
        regions.forEach(r -> {
            regionMap.put(r.getId(), r.getMergerName());
        });

        List<BusinessUnit> bus = businessUnitMapper.selectByExample(new BusinessUnitExample());
        Map<String, String> buMap = new HashMap<>();
        bus.forEach(bu -> {
            buMap.put(bu.getId(), bu.getName());
        });

        for (Organization o : orgs) {
            try {
                AnalysisMaster am = new AnalysisMaster();
                am.setId(idService.nextId());
                am.setSeqNo(o.getCode() + "" + period);
                List<Organization> parents = orgs.stream().filter(org -> org.getId().equals(o.getParentId())).collect(Collectors.toList());
                String parentAbbreviation = "";
                if (!parents.isEmpty()) {
                    parentAbbreviation = parents.get(0).getAbbreviation();
                }
                am.setParentCompanyAbbreviation(parentAbbreviation);
                am.setPeriod(period);
                am.setYear(period / 100);
                am.setMonth(period % 100);
                am.setFoundationDate(o.getFoundationDate());
                am.setName(o.getName());
                am.setArea(areaMap.get(o.getAreaId()));
                am.setCountry(o.getCountry());

                String regionMeg = regionMap.get(o.getRegionId());
                List<String> regionMs = Lists.newArrayList();
                if (StringUtils.isNotEmpty(regionMeg)) {
                    regionMs = Arrays.asList(regionMeg.split("."));
                }
                if (!regionMs.isEmpty()) {
                    am.setProvince(regionMs.get(1) != null ? regionMs.get(1) : "");
                    am.setCity(regionMs.get(2) != null ? regionMs.get(2) : "");
                    am.setDistrict(regionMs.get(3) != null ? regionMs.get(4) : "");
                }
                am.setBusinessLine(buMap.get(o.getBusinessUnitId()));
                am.setCode(o.getCode());
                am.setAbbreviation(o.getAbbreviation());
                am.setCurrencyCode(o.getCurrencyCode());
                am.setOrganizationId(o.getId());
                am.setCompanyName(o.getName());
                for (OrganizationAccountingRate rate : rates) {
                    if (o.getCurrencyCode().equals(rate.getCurrencyFrom())) {
                        am.setRate(rate.getRate());
                    }
                }
                analysisMasterMapper.insertSelective(am);
            } catch (Exception e) {
                logger.error(String.format("公司:[%s]生成机构分析数据失败!", o.getName()), e);
            }
        }
    }

    /**
     * 19/03/2019 15:55
     * VAT、CIT申报表取数
     * 1、根据机构、项目、期间、报表名称查出所有机构的增值税申报表
     * 2、获取该表的row、column、value 计算出部分segment[]1
     * 3、根据项目、机构、期间、Code-VAT100 查出对应机构的小微纳税人报表
     * 4、计算小微segment[]2并segment[]1合并
     * 5、获取利润表segment[]3
     * [orgs,period]
     *
     * @return
     * @author Gary J Li
     */
    public void analysisSales(List<Organization> orgs, Integer period,Integer type) {
        List<String> orgIds = orgs.stream().map(Organization::getId).collect(Collectors.toList());
        if(type.equals(EnumTbImportType.CoverImport.getCode())){
            AnalysisSalesExample example = new AnalysisSalesExample();
            example.createCriteria().andOrganizationIdIn(orgIds).andPeriodEqualTo(period);
            analysisSalesMapper.deleteByExample(example);
        }
        List<ProjectAnaylsisDto> vatDtos = projectMapper.getTemlateWithServiceType(orgIds, period / 100, period % 100, "增值税纳税申报表");
        Map<String, Organization> orgMap = orgs.stream().collect(Collectors.toMap(Organization::getId, Function.identity()));
        vatDtos.forEach(vatDto -> {
            Organization o = orgMap.get(vatDto.getOrgId());
            try {
                AnalysisSales as = new AnalysisSales();
                as.setId(idService.nextId());
                as.setSeqNo(o.getCode() + "" + period);

                List<AnalysisSalesValueDto> values = periodCellDataMapper.selectAnalysisSalesValueDto(vatDto.getReportId(), vatDto.getProjectId());

                Map<String, String> vMap = new HashMap<>();

                values.forEach(v -> {
                    vMap.put(v.getRowIndex() + "" + v.getColumnIndex(), v.getData());
                });
                vMap.get(9 + ":" + 18);
                // S-19  AJ-33
                BigDecimal segment1 = getSegmentAmount(vMap, 9, 18).
                        add(getSegmentAmount(vMap, 9, 32)).
                        add(getSegmentAmount(vMap, 13, 18)).
                        add(getSegmentAmount(vMap, 13, 32)).
                        add(getSegmentAmount(vMap, 15, 18)).
                        add(getSegmentAmount(vMap, 17, 18));

                BigDecimal segment2 = getSegmentAmount(vMap, 19, 18).add(getSegmentAmount(vMap, 19, 32));
                BigDecimal segment3 = getSegmentAmount(vMap, 20, 18).add(getSegmentAmount(vMap, 20, 32));
                BigDecimal segment4 = getSegmentAmount(vMap, 22, 18).add(getSegmentAmount(vMap, 22, 32));
                BigDecimal segment5 = getSegmentAmount(vMap, 21, 18).add(getSegmentAmount(vMap, 21, 32));
                BigDecimal segment6 = getSegmentAmount(vMap, 28, 18).add(getSegmentAmount(vMap, 28, 32));
                BigDecimal segment7 = getSegmentAmount(vMap, 29, 18).add(getSegmentAmount(vMap, 29, 32));
                BigDecimal segment8 = getSegmentAmount(vMap, 31, 18).add(getSegmentAmount(vMap, 31, 32));
                BigDecimal segment9 = getSegmentAmount(vMap, 32, 18).add(getSegmentAmount(vMap, 32, 32));
                BigDecimal segment10 = getSegmentAmount(vMap, 35, 18).add(getSegmentAmount(vMap, 35, 32));
                BigDecimal segment11 = getSegmentAmount(vMap, 42, 18).add(getSegmentAmount(vMap, 42, 32));

                // 查询小微纳税人表
                List<ProjectAnaylsisDto> tinyDto = projectMapper.getTemlateWithServiceType2(vatDto.getOrgId(), period / 100, period % 100, "VAT100");

                List<AnalysisSalesValueDto> tinyValues = Lists.newArrayList();

                if (!tinyDto.isEmpty()) {
                    tinyValues = periodCellDataMapper.selectAnalysisSalesValueDto(tinyDto.get(0).getReportId(), tinyDto.get(0).getProjectId());
                }
                if (!tinyValues.isEmpty()) {
                    Map<String, String> tvMap = new HashMap<>();

                    tinyValues.forEach(v -> {
                        tvMap.put(v.getRowIndex() + "" + v.getColumnIndex(), v.getData());
                    });

                    //E10+F10+E15+F15+E18+F18+E21+F21+E25+F25
                    BigDecimal segment1Tiny = getSegmentAmount(tvMap, 9, 4).
                            add(getSegmentAmount(tvMap, 9, 5)).
                            add(getSegmentAmount(tvMap, 14, 4)).
                            add(getSegmentAmount(tvMap, 14, 5)).
                            add(getSegmentAmount(tvMap, 17, 4)).
                            add(getSegmentAmount(tvMap, 17, 5)).
                            add(getSegmentAmount(tvMap, 20, 4)).
                            add(getSegmentAmount(tvMap, 20, 5)).
                            add(getSegmentAmount(tvMap, 24, 4)).
                            add(getSegmentAmount(tvMap, 24, 5));

                    //E32+F32
                    BigDecimal segment9Tiny = getSegmentAmount(tvMap, 31, 4).add(getSegmentAmount(tvMap, 31, 5));
                    //E33+F33
                    BigDecimal segment10Tiny = getSegmentAmount(tvMap, 32, 4).add(getSegmentAmount(tvMap, 32, 5));
                    //E34+F34
                    BigDecimal segment11Tiny = getSegmentAmount(tvMap, 33, 4).add(getSegmentAmount(tvMap, 33, 5));
                    //E29+F29+E30+F30+E31+F31
                    BigDecimal segment12 = getSegmentAmount(tvMap, 28, 4).
                            add(getSegmentAmount(tvMap, 28, 5)).
                            add(getSegmentAmount(tvMap, 29, 4)).
                            add(getSegmentAmount(tvMap, 29, 5)).
                            add(getSegmentAmount(tvMap, 30, 4)).
                            add(getSegmentAmount(tvMap, 30, 5));
                    //E30+F30
                    BigDecimal segment13 = getSegmentAmount(tvMap, 29, 4).add(getSegmentAmount(tvMap, 29, 5));
                    //E31+F31
                    BigDecimal segment14 = getSegmentAmount(tvMap, 30, 4).add(getSegmentAmount(tvMap, 30, 5));
                    as.setSegment12(segment12);
                    as.setSegment13(segment13);
                    as.setSegment14(segment14);

                    segment1 = segment1.add(segment1Tiny);
                    segment9 = segment9.add(segment9Tiny);
                    segment10 = segment10.add(segment10Tiny);
                    segment11 = segment11.add(segment11Tiny);
                }
                as.setSegment1(segment1);
                as.setSegment2(segment2);
                as.setSegment3(segment3);
                as.setSegment4(segment4);
                as.setSegment5(segment5);
                as.setSegment6(segment6);
                as.setSegment7(segment7);
                as.setSegment8(segment8);
                as.setSegment9(segment9);
                as.setSegment10(segment10);
                as.setSegment11(segment11);
                as.setSegment15(getPLData(vatDto, "一、营业收入"));
                as.setSegment16(getPLData(vatDto, "减:营业成本"));
                as.setSegment17(getPLData(vatDto, "三、利润总额(亏损总额以“-”号填列)"));
                //todo segment18需求未定义
                as.setOrganizationId(o.getId());
                as.setCompanyName(o.getName());
                as.setPeriod(period);
                analysisSalesMapper.insertSelective(as);
            } catch (Exception e) {
                logger.error(String.format("公司:[%s]生成申报表分析数据失败!", o.getName()), e);
            }

        });


    }

    private BigDecimal getPLData(ProjectAnaylsisDto vatDto, String itemName) {
        ProfitLossStatementExample e1 = new ProfitLossStatementExample();
        e1.createCriteria().andProjectIdEqualTo(vatDto.getProjectId()).andItemNameEqualTo(itemName);
        List<ProfitLossStatement> profitLossStatements = profitLossStatementFinalMapper.selectByExample(e1);
        if (profitLossStatements.isEmpty()) {
            return BigDecimal.ZERO;
        }
        // 返回本期发生额
        return profitLossStatements.get(0).getPeriodAmt();
    }

    private BigDecimal getSegmentAmount(Map<String, String> vMap, int row, int column) {
        return vMap.get(row + ":" + column) != null ? new BigDecimal(vMap.get(row + ":" + column)) : BigDecimal.ZERO;
    }

    /**
     * 19/03/2019 15:56
     * 计算返还后各税种税额  tax - actualReturn
     * [orgs,period]
     *
     * @return
     * @author Gary J Li
     */
    public void analysisTaxReturnEnd(List<Organization> orgs, Integer period,Integer type) {
        List<String> orgIds = orgs.stream().map(Organization::getId).collect(Collectors.toList());
        if(type.equals(EnumTbImportType.CoverImport.getCode())){
            AnalysisTaxReturnEndExample example = new AnalysisTaxReturnEndExample();
            example.createCriteria().andOrganizationIdIn(orgIds).andPeriodEqualTo(period);
            analysisTaxReturnEndMapper.deleteByExample(example);
        }

        AnalysisTaxExample e1 = new AnalysisTaxExample();
        e1.createCriteria().andOrganizationIdIn(orgIds).andPeriodEqualTo(period);
        List<AnalysisTax> ats = analysisTaxMapper.selectByExample(e1);

        AnalysisActualTaxReturnExample e2 = new AnalysisActualTaxReturnExample();
        e2.createCriteria().andOrganizationIdIn(orgIds).andPeriodEqualTo(period);
        List<AnalysisActualTaxReturn> aatrs = analysisActualTaxReturnMapper.selectByExample(e2);

        Map<String, List<AnalysisTax>> atMap = ats.stream().collect(Collectors.groupingBy(AnalysisTax::getOrganizationId));

        Map<String, List<AnalysisActualTaxReturn>> aatrMap = aatrs.stream().collect(Collectors.groupingBy(AnalysisActualTaxReturn::getOrganizationId));

        orgs.forEach(org -> {
            // 逐条取出机构的税额及实际返还税额计算 返还后税额入库
            List<AnalysisTax> orgATList = atMap.get(org.getId());
            List<AnalysisActualTaxReturn> orgAATRList = aatrMap.get(org.getId());
            generalAnaysisReturnTaxEnd(org, orgATList, orgAATRList);
        });

    }

    private void generalAnaysisReturnTaxEnd(Organization org, List<AnalysisTax> orgATList, List<AnalysisActualTaxReturn> aatrs) {
        BigDecimal selfTax = new BigDecimal(0);
        if(null!=orgATList){
            for (AnalysisTax at : orgATList) {
                if ("员工个税".equals(at.getTaxGroup()) || "司机个税".equals(at.getTaxGroup())) {
                    selfTax.add(at.getTaxAmount());
                }
                AnalysisTaxReturnEnd taxReturnEnd = new AnalysisTaxReturnEnd();
                taxReturnEnd.setId(idService.nextId());
                taxReturnEnd.setOrganizationId(org.getId());
                taxReturnEnd.setCompanyName(at.getCompanyName());
                taxReturnEnd.setPeriod(at.getPeriod());
                taxReturnEnd.setSeqNo(org.getCode() + "" + at.getPeriod());
                taxReturnEnd.setTaxGroup(at.getTaxGroup());
                BigDecimal taxAmount = at.getTaxAmount();
                // 该机构返还税信息不空时进行计算
                if(null!=aatrs){
                    if ("城建税".equals(at.getTaxGroup())) {
                        String returnTaxName = "城建税返还";
                        for (AnalysisActualTaxReturn attr : aatrs) {
                            if (returnTaxName.equals(attr.getTaxReturnGroup())) {
                                taxAmount = at.getTaxAmount().subtract(attr.getTaxReturnAmount());
                            }
                        }
                    } else if ("教育费附加".equals(at.getTaxGroup())) {
                        String returnTaxName = "教育费附加返还";
                        for (AnalysisActualTaxReturn attr : aatrs) {
                            if (returnTaxName.equals(attr.getTaxReturnGroup())) {
                                taxAmount = at.getTaxAmount().subtract(attr.getTaxReturnAmount());
                            }
                        }
                    } else if ("地方教育费附加".equals(at.getTaxGroup())) {
                        String returnTaxName = "地方教育费附加返还";
                        for (AnalysisActualTaxReturn attr : aatrs) {
                            if (returnTaxName.equals(attr.getTaxReturnGroup())) {
                                taxAmount = at.getTaxAmount().subtract(attr.getTaxReturnAmount());
                            }
                        }
                    } else if ("印花税".equals(at.getTaxGroup())) {
                        String returnTaxName = "增值税返还";
                        for (AnalysisActualTaxReturn attr : aatrs) {
                            if (returnTaxName.equals(attr.getTaxReturnGroup())) {
                                taxAmount = at.getTaxAmount().subtract(attr.getTaxReturnAmount());
                            }
                        }
                    }
                }

                taxReturnEnd.setTaxAmount(taxAmount);
                analysisTaxReturnEndMapper.insertSelective(taxReturnEnd);
            }

            BigDecimal selfTaxReturn = new BigDecimal(0);

            String returnTaxName = "个人所得税返还";
            // 该机构返还税信息不空时进行计算
            if (null != aatrs) {
                for (AnalysisActualTaxReturn attr : aatrs) {
                    if (returnTaxName.equals(attr.getTaxReturnGroup())) {
                        selfTaxReturn = attr.getTaxReturnAmount();
                    }
                }
            }
            // 个人所得税 = 员工个税 + 司机个税
            AnalysisTaxReturnEnd selfTaxReturnEnd = new AnalysisTaxReturnEnd();
            selfTaxReturnEnd.setId(idService.nextId());
            selfTaxReturnEnd.setOrganizationId(org.getId());
            selfTaxReturnEnd.setCompanyName(orgATList.get(0).getCompanyName());
            selfTaxReturnEnd.setPeriod(orgATList.get(0).getPeriod());
            selfTaxReturnEnd.setSeqNo(org.getCode() + "" + orgATList.get(0).getPeriod());
            selfTaxReturnEnd.setTaxGroup(orgATList.get(0).getTaxGroup());
            BigDecimal taxAmount = selfTax.subtract(selfTaxReturn);
            selfTaxReturnEnd.setTaxAmount(taxAmount);
            analysisTaxReturnEndMapper.insertSelective(selfTaxReturnEnd);
        }

    }

    /**
     * 19/03/2019 15:57
     * analysis_tax 与 organization_return_rate 计算预期返还税额
     * [orgs,period]
     *
     * @return
     * @author Gary J Li
     */
    public void analysisExpectedTax(List<Organization> orgs, Integer period,Integer type) {
        List<String> orgIds = orgs.stream().map(Organization::getId).collect(Collectors.toList());

        if(type.equals(EnumTbImportType.CoverImport.getCode())){
            AnalysisExpectedTaxReturnExample example = new AnalysisExpectedTaxReturnExample();
            example.createCriteria().andOrganizationIdIn(orgIds).andPeriodEqualTo(period);
            analysisExpectedTaxReturnMapper.deleteByExample(example);
        }
        OrganizationReturnRateExample e1 = new OrganizationReturnRateExample();
        e1.createCriteria().andOrganizationIdIn(orgIds).andStartDateLessThanOrEqualTo(new Date());
        List<OrganizationReturnRate> orrs = organizationReturnRateMapper.selectByExample(e1);

        AnalysisTaxExample e2 = new AnalysisTaxExample();
        e2.createCriteria().andPeriodEqualTo(period);
        List<AnalysisTax> ats = analysisTaxMapper.selectByExample(e2);

        Map<String, List<AnalysisTax>> atMap = ats.stream().collect(Collectors.groupingBy(AnalysisTax::getOrganizationId));

        atMap.forEach((k, v) -> {
            try {
                List<OrganizationReturnRate> orgsOrr = orrs.stream().filter(orr -> orr.getOrganizationId().equals(k)).collect(Collectors.toList());
                Map<String, List<OrganizationReturnRate>> orgOrrMap = orrs.stream().collect(Collectors.groupingBy(OrganizationReturnRate::getGroupName));
                AnalysisExpectedTaxReturn aetr = new AnalysisExpectedTaxReturn();
                aetr.setId(idService.nextId());
                aetr.setSeqNo(v.get(0).getSeqNo());
                for (AnalysisTax at : v) {
                    if ("增值税".equals(at.getTaxGroup()) && orgOrrMap.get(at.getTaxGroup()) != null) {
                        OrganizationReturnRate orr = orgOrrMap.get(at.getTaxGroup()).get(0);
                        aetr.setSegment1(new BigDecimal(at.getTaxAmount().floatValue() * orr.getReturnRate()));
                    } else if ("附加税".equals(at.getTaxGroup()) && orgOrrMap.get(at.getTaxGroup()) != null) {
                        OrganizationReturnRate orr = orgOrrMap.get(at.getTaxGroup()).get(0);
                        aetr.setSegment2(new BigDecimal(at.getTaxAmount().floatValue() * orr.getReturnRate()));
                    } else if ("个人所得税".equals(at.getTaxGroup()) && orgOrrMap.get(at.getTaxGroup()) != null) {
                        OrganizationReturnRate orr = orgOrrMap.get(at.getTaxGroup()).get(0);
                        aetr.setSegment2(new BigDecimal(at.getTaxAmount().floatValue() * orr.getReturnRate()));
                    }
                }
                aetr.setOrganizationId(k);
                aetr.setCompanyName(v.get(0).getCompanyName());
                aetr.setPeriod(period);
                analysisExpectedTaxReturnMapper.insertSelective(aetr);
            } catch (Exception e) {
                logger.error(String.format("公司:[%s]生成预期返还税额分析数据失败!", v.get(0).getCompanyName()), e);
            }
        });
    }

    /**
     * 19/03/2019 15:58
     * trial_balance_final 获取费用
     * [orgs,period]
     *
     * @return
     * @author Gary J Li
     */
    public void analysisFee(List<Organization> orgs, Integer period,Integer type) {
        List<String> orgIds = orgs.stream().map(Organization::getId).collect(Collectors.toList());
        if(type.equals(EnumTbImportType.CoverImport.getCode())){
            AnalysisFeeExample example = new AnalysisFeeExample();
            example.createCriteria().andOrganizationIdIn(orgIds).andPeriodEqualTo(period);
            analysisFeeMapper.deleteByExample(example);
        }

        TrialBalanceFinalExample e1 = new TrialBalanceFinalExample();
        e1.createCriteria().andPeriodEqualTo(period);
        List<TrialBalanceFinal> tbs = trialBalanceFinalMapper.selectByExample(e1);

        Map<String, List<TrialBalanceFinal>> tbMap = tbs.stream().collect(Collectors.groupingBy(TrialBalanceFinal::getOrganizationId));

        Map<String, Organization> orgMap = orgs.stream().collect(Collectors.toMap(Organization::getId, Function.identity()));

        tbMap.forEach((k, v) -> {
            v.forEach(tb -> {
                AnalysisFee af = new AnalysisFee();
                af.setId(idService.nextId());
                Organization org = orgMap.get(k);
                String subjectCode = tb.getSegment3();
                af.setSeqNo(org.getCode() + "" + period);
                af.setSubject(subjectCode);
                af.setFeeClassification1(tb.getAcctName1());
                af.setFeeClassification2(tb.getAcctName2());
                af.setFeeClassification3(tb.getAcctName3());
                // 这里费用取的  本位币本期借方发生额
                af.setFee(tb.getPeriodDrBeq());
                String interrelatedDeal = "";
                if (subjectCode.startsWith("6")) {
                    // 这里取得公司间代码是否为0
                    interrelatedDeal = "0".equals(tb.getSegment8()) ? "否" : "是";
                } else if (subjectCode.startsWith("8")) {
                    interrelatedDeal = "是";
                }
                af.setInterrelatedDeal(interrelatedDeal);
                af.setOrganizationId(org.getId());
                af.setCompanyName(org.getName());
                af.setPeriod(period);
                analysisFeeMapper.insertSelective(af);
            });
        });
    }

    /**
     * 19/03/2019 15:59
     * tax_document
     * [orgs,period]
     *
     * @return
     * @author Gary J Li
     */
    public void analysisFileManagement(List<Organization> orgs, Integer period,Integer type) {
        List<String> orgIds = orgs.stream().map(Organization::getId).collect(Collectors.toList());
        if(type.equals(EnumTbImportType.CoverImport.getCode())){
            AnalysisFileManagementExample example = new AnalysisFileManagementExample();
            example.createCriteria().andOrganizationIdIn(orgIds).andPeriodEqualTo(period);
            analysisFileManagementMapper.deleteByExample(example);
        }
        Map<String, Organization> orgMap = orgs.stream().collect(Collectors.toMap(Organization::getId, Function.identity()));
        TaxDocumentExample e1 = new TaxDocumentExample();
        e1.createCriteria().andCompanyIdIn(orgIds).andOwnTimeEqualTo(period);
        List<TaxDocument> taxDocuments = taxDocumentMapper.selectByExample(e1);

        List<OrganizationTaxRule> taxRules = organizationTaxRuleMapper.selectByExample(new OrganizationTaxRuleExample());

//        Map<String, OrganizationTaxRule> ruleMap = taxRules.stream().collect(Collectors.toMap(OrganizationTaxRule::getGroupName, Function.identity()));

        Map<String, List<OrganizationTaxRule>> ruleMap = taxRules.stream().collect(Collectors.groupingBy(OrganizationTaxRule::getGroupName));

        for(TaxDocument td : taxDocuments){
            Organization o = orgMap.get(td.getCompanyId());
            AnalysisFileManagement afm = new AnalysisFileManagement();
            afm.setId(idService.nextId());
            afm.setSeqNo(o.getCode() + "" + period);
            afm.setFileType(td.getFileType());

            // 周期性上传  校验当年的当前及之前的周期是否有上传文件
            if (StringUtils.isNotEmpty(td.getTaxType()) && null != td.getOwnTime()) {
                List<OrganizationTaxRule> otrs = ruleMap.get(td.getTaxType());

                Optional<OrganizationTaxRule> otrOP= otrs.stream().filter(otr->otr.getGroupName().equals(td.getTaxType())).map(OrganizationTaxRule::getUpdateTime).max(new ComparatorDate());
                OrganizationTaxRule rule = otrOP.get();
                if(null==rule){
                    break;
                }

                afm.setReportingFrequency(rule.getTaxDecCycle());
                String archivingStatus = "未归档";
                TaxDocumentExample example = new TaxDocumentExample();
                List<Integer> fileterTime = Lists.newArrayList();
                if ("年度".equals(rule.getTaxDecCycle())) {
                    Integer str = DateUtils.getNowYear() * 100;
                    Integer end = DateUtils.getNowYear() * 100 + 12;
                    example.createCriteria().andOwnTimeGreaterThanOrEqualTo(str).andOwnTimeLessThanOrEqualTo(end).andFileTypeEqualTo(td.getFileType());
                    archivingStatus = taxDocumentMapper.countByExample(example) > 0 ? "已归档" : archivingStatus;
                } else {
                    if ("月度".equals(rule.getTaxDecCycle())) {
                        fileterTime = MONTH_LIST.stream().filter(m -> m <= DateUtils.getNowMonth()).collect(Collectors.toList());
                    } else if ("季度".equals(rule.getTaxDecCycle())) {
                        fileterTime = Q_LIST.stream().filter(m -> m <= DateUtils.getNowMonth()).collect(Collectors.toList());
                    }
                    fileterTime.forEach(ft -> {
                        ft = DateUtils.getNowYear() * 100 + ft;
                    });
                    example.createCriteria().andOwnTimeIn(fileterTime).andFileTypeEqualTo(td.getFileType());
                    archivingStatus = taxDocumentMapper.countByExample(example) > 0 ? "已归档" : archivingStatus;
                }
                afm.setArchivingStatus(archivingStatus);
            }else{
                afm.setReportingFrequency("/");
                // 由于是根据文档列表查询 必然已归档
                afm.setArchivingStatus("已归档");
            }
            afm.setOrganizationId(o.getId());
            afm.setCompanyName(o.getName());
            afm.setPeriod(period);
            analysisFileManagementMapper.insertSelective(afm);
        }
    }

    public class ComparatorDate implements Comparator {

        public static final String TAG = "ComparatorDate";

        @Override
        public int compare(Object obj1, Object obj2) {
            Date d1 = (Date) obj1;
            Date d2 = (Date) obj2;
            if (d1.before(d2)) {
                return 1;
            } else {
                return -1;
            }
        }
    }
}