package com.tofly.xrtygis.custom.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tofly.common.oauth.exception.ToflyDeniedException;
import com.tofly.xrtygis.custom.entity.ImportDto.*;
import com.tofly.xrtygis.custom.entity.dto.WaterInfoDto;
import com.tofly.xrtygis.custom.mapper.ImportAboutMapper;
import com.tofly.xrtygis.custom.mapper.WaterMakingMapper;
import com.tofly.xrtygis.custom.service.ImportAboutService;
import com.tofly.xrtygis.custom.util.ImportWaterMaking;
import com.tofly.xrtygis.entity.*;
import com.tofly.xrtygis.service.*;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author 20126
 */
@Service
@AllArgsConstructor
public class ImportAboutServiceImpl implements ImportAboutService {

    private static final String COSTRLWATER = "TF_YWPN_COSTRLWATER_W";
    private static final String COSTRLUNIT = "TF_YWPN_COSTRLUNIT_W";
    private static final String COSTRLFIXED = "TF_YWPN_COSTRLFIXED_W";

    private final CostbgpriceService costbgpriceService;
    private final CostbgwaterService costbgwaterService;
    private final CostbgunitService costbgunitService;
    private final CostbgfixedService costbgfixedService;
    private final CostbgindexService costbgindexService;
    private final CostbgwateryearService costbgwateryearService;
    private final CostbgfixedyearService costbgfixedyearService;
    private final CostbgunityearService costbgunityearService;
    private final CostbgindexyearService costbgindexyearService;
    private final CostrlwaterService costrlwaterService;
    private final CostrlfixedService costrlfixedService;
    private final CostrlunitService costrlunitService;
    private final ImportAboutMapper importAboutMapper;
    private final WaterMakingMapper waterMakingMapper;
    private final CostcalcconfigService costcalcconfigService;

    /**
     * 制水成本计划管理导入
     *
     * @param dto dto
     * @return boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean importWaterMakingPlan(String dto) {
        if (null == dto) {
            throw new ToflyDeniedException("上传文件为空");
        }
        List<WaterPlanDto> waterPlanDtos = JSONObject.parseArray(dto, WaterPlanDto.class);
        List<IndexPlanDto> indexPlanDtos = JSONObject.parseArray(dto, IndexPlanDto.class);
        List<UnitPlanDto> unitPlanDtos = JSONObject.parseArray(dto, UnitPlanDto.class);

        //对年份进行收集去重
        List<String> waterCollect = waterPlanDtos.stream().map(WaterPlanDto::getYear).distinct().collect(Collectors.toList());
        //根据年份就行分组，根据月份就行排序
        Map<String, List<WaterPlanDto>> waterInfo = waterPlanDtos.stream().sorted(Comparator.comparing(WaterPlanDto::getMonth))
                .collect(Collectors.groupingBy(WaterPlanDto::getYear));
        Map<String, List<IndexPlanDto>> indexInfo = indexPlanDtos.stream().sorted(Comparator.comparing(IndexPlanDto::getMonth))
                .collect(Collectors.groupingBy(IndexPlanDto::getYear));
        Map<String, List<UnitPlanDto>> unitInfo = unitPlanDtos.stream().sorted(Comparator.comparing(UnitPlanDto::getMonth))
                .collect(Collectors.groupingBy(UnitPlanDto::getYear));
        //存放不存在单价的年份
        StringBuilder msg = new StringBuilder();
        //遍历年份
        for (String year : waterCollect) {
            //查询是否该年份单价
            List<Costbgprice> list = costbgpriceService.list(Wrappers.<Costbgprice>lambdaQuery()
                    .eq(Costbgprice::getYear, year));
            //为空跳过本次循环
            if (list.isEmpty()) {
                msg.append(" ").append(year);
            }
        }
        if (msg.length() > 0) {
            throw new ToflyDeniedException("请填报" + msg.toString().trim() + "年份单价信息");
        }
        //再次遍历年份
        for (String year : waterCollect) {
            //拿出最新创建的单价
            Costbgprice price = costbgpriceService.list(Wrappers.<Costbgprice>lambdaQuery()
                    .eq(Costbgprice::getYear, year).orderByDesc(Costbgprice::getCreateTime)).get(0);

            //对应年份的计划信息
            List<WaterPlanDto> waterList = waterInfo.get(year);
            List<IndexPlanDto> indexList = indexInfo.get(year);
            List<UnitPlanDto> unitList = unitInfo.get(year);

            if (waterList.size() != 12 || indexList.size() != 12 || unitList.size() != 12) {
                throw new ToflyDeniedException("请完善" + year + "年每月计划");
            }

            Costbgwateryear waterYear = costbgwateryearService.getOne(Wrappers.<Costbgwateryear>lambdaQuery()
                    .eq(Costbgwateryear::getYear, year));
            Costbgfixedyear fixedYear = costbgfixedyearService.getOne(Wrappers.<Costbgfixedyear>lambdaQuery()
                    .eq(Costbgfixedyear::getYear, year));
            Costbgunityear unitYear = costbgunityearService.getOne(Wrappers.<Costbgunityear>lambdaQuery()
                    .eq(Costbgunityear::getYear, year));
            Costbgindexyear indexYear = costbgindexyearService.getOne(Wrappers.<Costbgindexyear>lambdaQuery()
                    .eq(Costbgindexyear::getYear, year));

            Long waterYearId = null;
            if (waterYear == null) {
                Costbgwateryear costbgwateryear = new Costbgwateryear();
                costbgwateryear.setYear(year);
                costbgwateryear.setState("1");
                costbgwateryear.setOverTime(new Date());
                costbgwateryearService.save(costbgwateryear);
                waterYearId = costbgwateryear.getId();
            }

            Long unitYearId = null;
            if (null == unitYear) {
                Costbgunityear costbgunityear = new Costbgunityear();
                costbgunityear.setState("1");
                costbgunityear.setYear(year);
                costbgunityear.setOverTime(new Date());
                costbgunityearService.save(costbgunityear);
                unitYearId = costbgunityear.getId();
            }

            Long fixedYearId = null;
            if (null == fixedYear) {
                Costbgfixedyear costbgfixedyear = new Costbgfixedyear();
                costbgfixedyear.setState("1");
                costbgfixedyear.setOverTime(new Date());
                costbgfixedyear.setYear(year);
                costbgfixedyearService.save(costbgfixedyear);
                fixedYearId = costbgfixedyear.getId();
            }

            Long indexYearId = null;
            if (null == indexYear) {
                Costbgindexyear costbgindexyear = new Costbgindexyear();
                costbgindexyear.setState("1");
                costbgindexyear.setOverTime(new Date());
                costbgindexyear.setYear(year);
                costbgindexyearService.save(costbgindexyear);
                indexYearId = costbgindexyear.getId();
            }

            for (int i = 0; i < 12; i++) {
                WaterPlanDto water = waterList.get(i);
                IndexPlanDto index = indexList.get(i);
                UnitPlanDto unit = unitList.get(i);

                Costbgwater costbgwater = ImportWaterMaking.calTbgWater(water);
                //为空则直接添加，不为空修改
                if (null == waterYear || "0".equals(waterYear.getState())) {
                    costbgwater.setYearId(waterYearId);
                    costbgwaterService.save(costbgwater);
                } else {
                    Costbgwater one = costbgwaterService.getOne(Wrappers.<Costbgwater>lambdaQuery()
                            .eq(Costbgwater::getMonth, water.getYear() + "-" + water.getMonth())
                            .eq(Costbgwater::getYearId, waterYear.getId())
                            .select(Costbgwater::getId));

                    costbgwater.setId(one.getId());
                    costbgwater.setYearId(waterYear.getId());

                    costbgwaterService.updateById(costbgwater);

                    costbgwateryearService.update(Wrappers.<Costbgwateryear>lambdaUpdate()
                            .eq(Costbgwateryear::getId, waterYear.getId())
                            .set(Costbgwateryear::getState, "1")
                            .set(Costbgwateryear::getOverTime, new Date()));
                }

                Costbgindex costbgindex = ImportWaterMaking.calTbgIndex(unit, costbgwater, index);

                if (null == indexYear || "0".equals(indexYear.getState())) {
                    costbgindex.setYearId(indexYearId);
                    costbgindexService.save(costbgindex);
                } else {
                    Costbgindex one = costbgindexService.getOne(Wrappers.<Costbgindex>lambdaQuery()
                            .eq(Costbgindex::getYearId, indexYear.getId())
                            .eq(Costbgindex::getMonth, costbgwater.getMonth())
                            .select(Costbgindex::getId));

                    costbgindex.setYearId(indexYear.getId());
                    costbgindex.setId(one.getId());

                    costbgindexService.updateById(costbgindex);

                    costbgindexyearService.update(Wrappers.<Costbgindexyear>lambdaUpdate()
                            .eq(Costbgindexyear::getId, indexYear.getId())
                            .set(Costbgindexyear::getState, "1")
                            .set(Costbgindexyear::getOverTime, new Date()));
                }

                Costbgunit costbgunit = ImportWaterMaking.calTbgUnit(costbgwater, unit);

                if (null == unitYear || "0".equals(unitYear.getState())) {
                    costbgindex.setYearId(unitYearId);
                    costbgunitService.save(costbgunit);
                } else {
                    Costbgunit one = costbgunitService.getOne(Wrappers.<Costbgunit>lambdaQuery()
                            .eq(Costbgunit::getYearId, unitYear.getId())
                            .eq(Costbgunit::getMonth, costbgwater.getMonth())
                            .select(Costbgunit::getId));

                    costbgunit.setYearId(unitYear.getId());
                    costbgunit.setId(one.getId());

                    costbgunitService.updateById(costbgunit);

                    costbgunityearService.update(Wrappers.<Costbgunityear>lambdaUpdate()
                            .eq(Costbgunityear::getId, unitYear.getId())
                            .set(Costbgunityear::getOverTime, new Date())
                            .set(Costbgunityear::getState, "1"));
                }

                Costbgfixed costbgfixed = ImportWaterMaking.calTbgFixed(costbgwater, price, costbgindex,water.getJbdfOne(),water.getJbdfTwo());

                if (null == fixedYear || "0".equals(fixedYear.getState())) {
                    costbgfixed.setYearId(fixedYearId);
                    costbgfixedService.save(costbgfixed);
                } else {
                    Costbgfixed one = costbgfixedService.getOne(Wrappers.<Costbgfixed>lambdaQuery()
                            .eq(Costbgfixed::getYearId, fixedYear.getId())
                            .eq(Costbgfixed::getMouth, costbgwater.getMonth())
                            .select(Costbgfixed::getId));

                    costbgfixed.setYearId(fixedYear.getId());
                    costbgfixed.setId(one.getId());

                    costbgfixedService.updateById(costbgfixed);

                    costbgfixedyearService.update(Wrappers.<Costbgfixedyear>lambdaUpdate()
                            .eq(Costbgfixedyear::getId, fixedYear.getId())
                            .set(Costbgfixedyear::getCreateTime, new Date())
                            .set(Costbgfixedyear::getState, "1"));
                }
            }
        }
        return true;
    }

    /**
     * 制水成本实际管理导入
     *
     * @param dto dto
     * @return boolean
     */
    @Override
    public boolean importWaterMaking(String dto) {
        if (dto.isEmpty()) {
            throw new ToflyDeniedException("传入数据为空");
        }
        List<WaterDto> waterDtos = JSONObject.parseArray(dto, WaterDto.class);

        if (null != waterDtos && waterDtos.size() > 0) {

            //取得年份，对其进行分组去重
            List<String> yearList = waterDtos.stream().map(WaterDto::getYear).distinct().collect(Collectors.toList());

            //对数据进行分组排序
            Map<String, List<WaterDto>> waterGroup = waterDtos.stream()
                    .sorted(Comparator.comparing(WaterDto::getUpDate))
                    .collect(Collectors.groupingBy(WaterDto::getYear));

            yearList.forEach(year->{

                List<WaterDto> waterDtoList = waterGroup.get(year);

                for (WaterDto waterDto : waterDtoList) {

                    Costrlwater water = ImportWaterMaking.calTrlWater(waterDto);
                    Long waterId = importAboutMapper.existDate(COSTRLWATER, water.getMark(), water.getUpDate());

                    if (null == waterId) {
                        costrlwaterService.save(water);
                    } else {
                        water.setId(waterId);
                        costrlwaterService.updateById(water);
                    }
                    Costrlunit unit = ImportWaterMaking.calTrlUnit(water);
                    unit.setMark("0");
                    Long unitId = importAboutMapper.existDate(COSTRLUNIT, unit.getMark(), unit.getUpDate());
                    if (null == unitId){
                        costrlunitService.save(unit);
                    }else {
                        unit.setId(unitId);
                        costrlunitService.updateById(unit);
                    }
                }
            });
        }
        return true;
    }

    /**
     * 财务填报导入
     *
     * @param dto dto
     * @return boolean
     */
    @Override
    public boolean importFixed(String dto) {
        if (dto.isEmpty()){
            throw new ToflyDeniedException("上传数据为空");
        }
        List<FixedDto> fixedDtoList = JSONObject.parseArray(dto, FixedDto.class);

        List<String> yearList = fixedDtoList.stream().map(FixedDto::getYear)
                .distinct().collect(Collectors.toList());

        if (!yearList.isEmpty()){
            StringBuilder msg = new StringBuilder();
            yearList.forEach(year->{
                if (null == importAboutMapper.viewPrice(year)){
                    msg.append(" ").append(year);
                }
            });

            if (msg.length() > 0){
                throw new ToflyDeniedException("请填报" + msg.toString().trim() + "年份单价信息");
            }

            Map<String, List<FixedDto>> fixedList = fixedDtoList.stream().sorted(Comparator.comparing(FixedDto::getUpDate))
                    .collect(Collectors.groupingBy(FixedDto::getYear));

            Costcalcconfig config = costcalcconfigService.getById(1);

            for (String year : yearList) {
                List<FixedDto> fixedDtos = fixedList.get(year);

                Costrlprice price = importAboutMapper.viewPrice(year);

                fixedDtos.forEach(fixedDto->{
                    WaterInfoDto infoSum = waterMakingMapper.getWaterInfoSum(fixedDto.getUpDate(),config.getStartDate(),config.getEndDate());
                    Costrlwater costrlwater = ImportWaterMaking.calWaterInfo(fixedDto, infoSum, price);
                    Long aLong = importAboutMapper.existDate(COSTRLWATER, "1", fixedDto.getUpDate());

                    if (null != aLong){
                        costrlwater.setId(aLong);
                        costrlwaterService.updateById(costrlwater);
                    }else {
                        costrlwaterService.save(costrlwater);
                    }

                    Costrlunit unit = ImportWaterMaking.calTrlUnit(costrlwater);

                    Long aLong1 = importAboutMapper.existDate(COSTRLUNIT, "1", costrlwater.getUpDate());

                    if (null == aLong1){
                        costrlunitService.save(unit);
                    }else {
                        unit.setId(aLong1);
                        costrlunitService.updateById(unit);
                    }

                    Costrlfixed fixed = ImportWaterMaking.calFixedInfo(fixedDto, price, costrlwater);
                    Long aLong2 = importAboutMapper.existDate(COSTRLFIXED, "1", costrlwater.getUpDate());

                    if (null == aLong2){
                        costrlfixedService.save(fixed);
                    }else {
                        fixed.setId(aLong2);
                        costrlfixedService.updateById(fixed);
                    }
                });
            }
        }
        return true;
    }

}
