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

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tofly.common.core.util.DateUtil;
import com.tofly.common.ftp.config.FtpUtil;
import com.tofly.common.oauth.exception.ToflyDeniedException;
import com.tofly.xrtygis.config.FilePathBean;
import com.tofly.xrtygis.custom.entity.dto.FixedDto;
import com.tofly.xrtygis.custom.entity.dto.WaterInfoDto;
import com.tofly.xrtygis.custom.entity.em.FillInStateEnum;
import com.tofly.xrtygis.custom.entity.vo.WaterVo;
import com.tofly.xrtygis.custom.mapper.CosTprStationMapper;
import com.tofly.xrtygis.custom.mapper.WaterCostMapper;
import com.tofly.xrtygis.custom.mapper.WaterMakingMapper;
import com.tofly.xrtygis.custom.service.WaterMakingService;
import com.tofly.xrtygis.custom.util.CommonMethod;
import com.tofly.xrtygis.custom.util.service.FileInfoService;
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 org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 20126
 */
@Service
@AllArgsConstructor
public class WaterMakingServiceImpl implements WaterMakingService {

    private final static String TABLE_NAME = "TF_YWPN_COSTRLWATER_W";
    private final static String TABLE_UNIT = "TF_YWPN_COSTRLUNIT_W";
    private final static String TABLE_FIXED = "TF_YWPN_COSTRLFIXED_W";

    private final FileInfoService fileInfoService;
    private final CostnotesService costnotesService;
    private final CostrlwaterService costrlwaterService;
    private final FilePathBean filePathBean;
    private final WaterCostMapper waterCostMapper;
    private final CostrlunitService costrlunitService;
    private final FileService fileService;
    private final CostrlpriceService costrlpriceService;
    private final CostrlfixedService costrlfixedService;
    private final CostcalcconfigService costcalcconfigService;

    private final WaterMakingMapper waterMakingMapper;
    private final CosTprStationMapper cosTprStationMapper;

    /**
     * 填报制水指标（可上传文件和备注）
     *
     * @param fileList 上传文件
     * @param water    制水指标
     * @param notes    备注说明
     * @return boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertWaterIndex(List<MultipartFile> fileList, Costrlwater water, String notes) {
        //判断当前填报日期数据是否存在
        if (FillInStateEnum.FINANCE.getState().equals(water.getMark())) {
            WaterVo waterVo = waterCostMapper.financeByMonth(DateUtil.getDateFormat(water.getUpDate(), "yyyy-MM"));
            if (waterVo != null) {
                throw new ToflyDeniedException("本月已进行财务填报");
            }
        } else {
            Long infoByDay = waterCostMapper.getInfoByDay(TABLE_NAME, DateUtil.getDateFormat(water.getUpDate(), "yyyy-MM-dd"),"0");
            if (null != infoByDay) {
                throw new ToflyDeniedException("该天已进行非财务填报");
            }
        }
        //计算相关数据并保存
        Costrlwater costrlwater = CommonMethod.calWater(water);
        costrlwaterService.save(costrlwater);

        //添加备注表信息
        Costnotes costnotes = new Costnotes();

        if (!fileList.isEmpty()) {
            //文件保存
            StringBuilder fileids = fileInfoService.saveFileList(fileList, filePathBean.getCostNotesFile(), TABLE_NAME);
            costnotes.setFileids(fileids.toString());
        }
        costnotes.setUpid(costrlwater.getId());
        costnotes.setNotes(notes);
        costnotes.setUpDate(water.getUpDate());

        costnotesService.save(costnotes);

        waterInsertAbout(costrlwater);
        return true;
    }

    /**
     * 查询备注信息
     *
     * @param waterId 指标id
     * @return Costnotes
     */
    @Override
    public Costnotes getNotesInfo(Long waterId) {
        return costnotesService.getOne(Wrappers.<Costnotes>lambdaQuery().eq(Costnotes::getUpid, waterId));
    }

    /**
     * 修改制水指标
     *
     * @param fileList    上传文件
     * @param costrlwater 制水指标
     * @param notes       备注
     * @return true of false
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateWaterIndex(List<MultipartFile> fileList, Costrlwater costrlwater, String notes) {
        //首先修改制水指标信息
        Costrlwater water = CommonMethod.calWater(costrlwater);
        costrlwaterService.updateById(water);

        Costnotes costnotes = costnotesService.getOne(Wrappers.<Costnotes>lambdaQuery()
                .eq(Costnotes::getUpid, costrlwater.getId()));

        if (costnotes != null) {
            if (!fileList.isEmpty()) {

                if (costnotes.getFileids() != null) {

                    List<String> paths = Collections.singletonList(costnotes.getFileids());

                    List<String> collect = fileService.list(Wrappers.<File>lambdaQuery()
                            .in(File::getId, paths))
                            .stream().map(File::getFilePath).collect(Collectors.toList());
                    for (String path : collect) {
                        FtpUtil.deleteFile(path);
                    }
                    fileService.removeByIds(paths);
                }
                StringBuilder fileids = fileInfoService.saveFileList(fileList, filePathBean.getCostNotesFile(), TABLE_NAME);
                costnotes.setFileids(fileids.toString());
            }
            if (null != notes) {
                costnotes.setNotes(notes);
            }
            costnotesService.updateById(costnotes);
        }

        waterInsertAbout(water);
        return true;
    }

    /**
     * 填报实际单价
     *
     * @param costrlprice 实际单价
     * @return boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertPrice(Costrlprice costrlprice) {
        //id为空或0添加 不为空修改
        if (null == costrlprice.getId() || costrlprice.getId() < 1) {
            //查询是否存在最新单价
            Costrlprice price = costrlpriceService.getOne(Wrappers.<Costrlprice>lambdaQuery()
                    .select(Costrlprice::getId)
                    .eq(Costrlprice::getYear, costrlprice.getYear())
                    .eq(Costrlprice::getIsnew, FillInStateEnum.FINANCE.getState()));
            //有的话将当前单价状态修改为旧
            if (null != price) {
                costrlpriceService.update(Wrappers.<Costrlprice>lambdaUpdate()
                        .eq(Costrlprice::getId, price.getId())
                        .set(Costrlprice::getIsnew, FillInStateEnum.NON_FINANCIAL.getState()));
            }
            costrlprice.setIsnew(FillInStateEnum.FINANCE.getState());
            costrlpriceService.save(costrlprice);
        } else {
            costrlpriceService.updateById(costrlprice);
        }

        //查询当前月是否进行了单变的财务填报
        Long tableId = waterMakingMapper.getTableInfo(new Date(), FillInStateEnum.FINANCE.getState(), TABLE_FIXED);

        if (null != tableId) {
            Costrlfixed fixed = costrlfixedService.getById(tableId);
            WaterInfoDto waterInfo = waterMakingMapper.getWaterInfoSum(new Date());
            //计算水量指标财务填报数据
            Costrlwater costrlwater = CommonMethod.calWaterInfo(costrlprice, fixed, waterInfo);

            Long waterId = waterMakingMapper.getTableInfo(new Date(), FillInStateEnum.FINANCE.getState(), TABLE_NAME);
            //水量指标财务填报存在则进行修改
            if (null != waterId) {
                costrlwater.setId(waterId);
                costrlwaterService.updateById(costrlwater);
            } else {
                //不存在则添加财务填报
                costrlwaterService.save(costrlwater);
            }
            Costrlunit unit = CommonMethod.newCalUnit(costrlwater);
            Long unitId = waterMakingMapper.getTableInfo(new Date(), FillInStateEnum.FINANCE.getState(), TABLE_UNIT);
            if (null != unitId) {
                unit.setId(unitId);
                costrlunitService.updateById(unit);
            } else {
                costrlunitService.save(unit);
            }
            Costrlfixed calFixed = CommonMethod.newCalFixed(fixed, costrlwater);
            calFixed.setId(tableId);
            costrlfixedService.updateById(calFixed);
        }

        Long fixedId = waterMakingMapper.getTableInfo(new Date(), FillInStateEnum.NON_FINANCIAL.getState(), TABLE_FIXED);

        Costrlfixed fixed;
        Costrlwater water = waterMakingMapper.getWater(new Date(),FillInStateEnum.NON_FINANCIAL.getState());

        if (null != water){
            fixed = CommonMethod.newCalFixed(CommonMethod.calExpense(costrlprice, water), water);
            fixed.setMark("0");
            if (null != fixedId) {
                fixed.setId(fixedId);
                costrlfixedService.updateById(fixed);
            } else {
                costrlfixedService.save(fixed);
            }
        }
        return true;
    }

    /**
     * 修改实际单价
     *
     * @param price 实际单价
     * @return boolean
     */
    @Override
    public boolean updatePrice(Costrlprice price) {
        if (null == price) {
            throw new ToflyDeniedException("数据不允许为空");
        }
        if (null != price.getId()) {
            //将当前单价修改为历史单价
            costrlpriceService.update(Wrappers.<Costrlprice>lambdaUpdate()
                    .eq(Costrlprice::getId, price.getId()).set(Costrlprice::getIsnew, 0));
            //添加为最新单价
            price.setIsnew("1");
            costrlpriceService.save(price);

            Long waterId = waterMakingMapper.getTableInfo(new Date(), "0", TABLE_NAME);

            if (null != waterId) {
                Costrlwater water = costrlwaterService.getById(waterId);
                Costrlfixed fixed = CommonMethod.newCalFixed(CommonMethod.calExpense(price, water), water);

                Long fixedId = waterMakingMapper.getTableInfo(new Date(), "0", TABLE_FIXED);

                fixed.setMark("0");

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

    /**
     * 模拟纠偏
     *
     * @param month 月份
     * @return list
     */
    @Override
    public Map<String, Object> simulationCorrection(String month,String code) {
        Map<String, Object> result = new HashMap<>(2);

        if(code == null || "".equals(code)){
            throw new ToflyDeniedException("未进行选择");
        }

        switch (code){
            //月财务与月计划
            case "0":
                result.put("actual",waterMakingMapper.simulationCorrection(month));
                result.put("plan",waterMakingMapper.getMonthPlan(month));
                break;
            //年财务与年计划
            case "1":
                result.put("actual",waterMakingMapper.simulationCorrectionYear(month));
                result.put("plan",waterMakingMapper.getMonthPlanYear(month));
                break;
            default:
        }
        return result;
    }

    /**
     * 获取计算配置信息
     *
     * @return Costcalcconfig
     */
    @Override
    public Costcalcconfig getInfo() {
        return costcalcconfigService.getById(1);
    }

    /**
     * 处理单变
     *
     * @param dto dto
     * @return boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertFixed(FixedDto dto) {

        if (dto.getUpDate() == null) {
            throw new ToflyDeniedException("填报时间不允许为空");
        }
        if (FillInStateEnum.FINANCE.getState().equals(dto.getMark())) {
            Long finance = cosTprStationMapper.isFinance(DateUtil.getDateFormat(dto.getUpDate(), "yyyy-MM"), TABLE_FIXED, null);

            if (null != finance) {
                throw new ToflyDeniedException("本月已进行财务填报");
            }
        } else {
            Long infoByDay = waterCostMapper.getInfoByDay(TABLE_FIXED, DateUtil.getDateFormat(dto.getUpDate(), "yyyy-MM-dd"),"0");
            if (null != infoByDay) {
                throw new ToflyDeniedException("该天已进行非财务填报");
            }
        }
        Long priceId = waterMakingMapper.getPriceID(dto.getUpDate());

        Costrlfixed fixed = fixedAssignment(dto);

        if (null != priceId) {
            Costrlfixed costrlfixed = handerFixed(dto, fixed, priceId);
            costrlfixedService.save(costrlfixed);

        } else {
            costrlfixedService.save(fixed);
        }
        return true;
    }

    @Override
    public boolean updateFixed(FixedDto dto) {

        if (null == dto.getId()) {
            throw new ToflyDeniedException("id不能为空");
        }

        Costrlfixed fixed = fixedAssignment(dto);

        Long priceId = waterMakingMapper.getPriceID(dto.getUpDate());

        if (null != priceId) {
            Costrlfixed costrlfixed = handerFixed(dto, fixed, priceId);

            costrlfixedService.updateById(costrlfixed);
        } else {
            costrlfixedService.updateById(fixed);
        }
        return true;
    }

    private Costrlfixed handerFixed(FixedDto dto, Costrlfixed fixed, Long priceId) {
        Costrlprice price = costrlpriceService.getById(priceId);
        WaterInfoDto infoSum = waterMakingMapper.getWaterInfoSum(dto.getUpDate());

        Costrlwater water = CommonMethod.calWaterInfo(price, dto, infoSum);

        Long waterId = waterMakingMapper.getTableInfo(dto.getUpDate(), dto.getMark(), TABLE_NAME);
        if (null != waterId) {
            water.setId(waterId);
            costrlwaterService.updateById(water);
        } else {
            costrlwaterService.save(water);
        }
        Long unitId = waterMakingMapper.getTableInfo(dto.getUpDate(), dto.getMark(), TABLE_UNIT);
        Costrlunit unit = CommonMethod.newCalUnit(water);
        if (unitId != null) {
            unit.setId(unitId);
            costrlunitService.updateById(unit);
        } else {
            costrlunitService.save(unit);
        }
        fixed.setDldfOne(CommonMethod.divide(CommonMethod.multiply(water.getDldlOne(), price.getDlddjOne()),10000D));
        fixed.setDldfTwo(CommonMethod.divide(CommonMethod.multiply(water.getDldlTwo(), price.getDlddjTwo()),10000D));
        fixed.setDldfTotal(CommonMethod.add(fixed.getDldfOne(), fixed.getDldfTwo()));
        fixed.setJbdfOne(CommonMethod.divide(CommonMethod.multiply(water.getJbdlOne(), price.getDlddjOne()),10000D));
        fixed.setJbdfTwo(CommonMethod.divide(CommonMethod.multiply(water.getJbdlTwo(), price.getDlddjOne()),10000D));
        fixed.setJbdfTotal(CommonMethod.add(fixed.getJbdfOne(), fixed.getJbdfTwo()));
        fixed.setZfyOne(CommonMethod.add(CommonMethod.add(CommonMethod.add(fixed.getJbdfOne(), fixed.getDldfOne()), CommonMethod.add(fixed.getZzsclfyOne(), fixed.getYsf())), fixed.getSzysfOne()));
        fixed.setZfyTwo(CommonMethod.add(CommonMethod.add(fixed.getJbdfTwo(), fixed.getDldfTwo()), CommonMethod.add(fixed.getZzsclfyTwo(), fixed.getSzysfTwo())));
        fixed.setZfy(CommonMethod.add(fixed.getZfyOne(), fixed.getZfyTwo()));

        return CommonMethod.newCalFixed(fixed, water);
    }

    public static Costrlfixed fixedAssignment(FixedDto dto) {
        Costrlfixed fixed = JSONObject.parseObject(JSONObject.toJSONString(dto), Costrlfixed.class);

        fixed.setSzysfTotal(CommonMethod.add(fixed.getSzysfOne(), fixed.getSzysfTwo()));
        fixed.setZzsclfyOne(CommonMethod.add(CommonMethod.add(dto.getSyzfyOne(), dto.getCnzfy()), CommonMethod.add(dto.getPaczfyOne(), dto.getBcszfy())));
        fixed.setZzsclfyTwo(CommonMethod.add(CommonMethod.add(CommonMethod.add(dto.getPaczfyTwo(), dto.getYlzfyTwo()), CommonMethod.add(dto.getPamzszfy(), dto.getFtzfy())),
                CommonMethod.add(CommonMethod.add(dto.getGmsjfhyzfy(), dto.getPamwnzfy()), dto.getWnzyf())));
        return fixed;
    }

    /**
     * 制水指标相关公共代码
     *
     * @param water 制水指标
     */
    private void waterInsertAbout(Costrlwater water) {
        //计算单耗信息
        Costrlunit costrlunit = CommonMethod.newCalUnit(water);

        Long unitInfo = waterMakingMapper.getTableInfo(water.getUpDate(), water.getMark(), TABLE_UNIT);

        if (null == unitInfo) {
            costrlunitService.save(costrlunit);
        } else {
            costrlunit.setId(unitInfo);
            costrlunitService.updateById(costrlunit);
        }
        //取出填报年份
        String year = DateUtil.getDateFormat(water.getUpDate(), "yyyy");
        //查询单价信息
        Costrlprice price = costrlpriceService.getOne(Wrappers.<Costrlprice>lambdaQuery()
                .eq(Costrlprice::getYear, year).eq(Costrlprice::getIsnew, "1"));
        //查询指标单价不为空
        if (null != price) {
            //计算费用
            Costrlfixed fixed = CommonMethod.calExpense(price, water);
            Costrlfixed costrlfixed = CommonMethod.newCalFixed(fixed, water);

            Long fixedId = waterMakingMapper.getTableInfo(water.getUpDate(), water.getMark(), TABLE_FIXED);
            costrlfixed.setMark("0");
            costrlfixed.setUpDate(water.getUpDate());
            if (null == fixedId) {
                costrlfixedService.save(costrlfixed);
            } else {
                costrlfixed.setId(fixedId);
                costrlfixedService.updateById(fixed);
            }
        }
    }


}
