package com.jeeplus.pubmodules.wareHouse.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.collect.Lists;
import com.jeeplus.common.TokenProvider;
import com.jeeplus.core.query.QueryWrapperGenerator;
import com.jeeplus.flowable.feign.IFlowableApi;
import com.jeeplus.pubmodules.oss.domain.WorkAttachment;
import com.jeeplus.pubmodules.oss.mapper.OssServiceMapper;
import com.jeeplus.pubmodules.oss.service.OssService;
import com.jeeplus.pubmodules.oss.service.dto.WorkAttachmentDto;
import com.jeeplus.pubmodules.purchase.domain.MaterialBasic;
import com.jeeplus.pubmodules.purchase.domain.MaterialDetailed;
import com.jeeplus.pubmodules.purchase.mapper.MaterialBasicMapper;
import com.jeeplus.pubmodules.purchase.mapper.MaterialDetailedMapper;
import com.jeeplus.pubmodules.purchase.service.MaterialService;
import com.jeeplus.pubmodules.serialNumTpl.service.SerialnumTplService;
import com.jeeplus.pubmodules.supplier.domain.MaterialSupplier;
import com.jeeplus.pubmodules.supplier.mapper.MaterialSupplierMapper;
import com.jeeplus.pubmodules.wareHouse.domain.WareHouseBasic;
import com.jeeplus.pubmodules.wareHouse.domain.WareHouseDetailed;
import com.jeeplus.pubmodules.wareHouse.domain.WarehouseUpHi;
import com.jeeplus.pubmodules.wareHouse.mapper.WareHouseBasicMapper;
import com.jeeplus.pubmodules.wareHouse.mapper.WareHouseDetailedMapper;
import com.jeeplus.pubmodules.wareHouse.mapper.WareHouseSummaryMapper;
import com.jeeplus.pubmodules.wareHouse.mapper.WarehouseUpHiMapper;
import com.jeeplus.pubmodules.wareHouse.service.dto.WareHouseDto;
import com.jeeplus.sys.feign.IUserApi;
import com.jeeplus.sys.service.dto.UserDTO;
import com.jeeplus.utils.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;

/**
 * @author: 王强
 * @create: 2022-12-29 14:19
 **/
@Service
@Transactional
public class WareHouseBasicService {

    @Resource
    private MaterialBasicMapper materialBasicMapper;

    @Resource
    private WareHouseBasicMapper basicMapper;

    @Resource
    private WareHouseDetailedMapper detailedMapper;

    @Resource
    private WareHouseSummaryMapper summaryMapper;

    @Resource
    private MaterialDetailedMapper materialDetailedMapper;

    @Resource
    private OssServiceMapper ossServiceMapper;

    @Resource
    private SerialnumTplService serialnumTplService;

    @Resource
    private MaterialService basicService;

//    @Resource
//    private ContractInfoService infoService;

    @Resource
    private IFlowableApi flowTaskService;

    @Resource
    private WarehouseUpHiMapper warehouseUpHiMapper;

    @Resource
    private WareHouseBasicMapper wareHouseBasicMapper;

    @Resource
    private OssService ossService;

    @Resource
    private MaterialSupplierMapper materialSupplierMapper;

    /**
     * 列表查询
     */
    public IPage<WareHouseDto> wareHouseHistoryList(Page<WareHouseDto> page , WareHouseDto dto) throws Exception{
        QueryWrapper<WareHouseDto> queryWrapper = QueryWrapperGenerator.buildQueryCondition(dto, WareHouseDto.class);

        queryWrapper.eq("a.del_flag", "0");

        if (StringUtils.isNotBlank(dto.getDetailId())) {
            queryWrapper.eq("b.id", dto.getDetailId());
        }

        if (StringUtils.isNotEmpty(dto.getTradeName())) {
            queryWrapper.eq("b.trade_name", dto.getTradeName());
        }

        if (StringUtils.isNotEmpty(dto.getWareHouseNumber())) {
            queryWrapper.eq("a.ware_house_number", dto.getWareHouseNumber());
        }

        String[] wareHouseDates = dto.getWareHouseDates();
        if (wareHouseDates != null) {

            queryWrapper.between("a.ware_house_date", wareHouseDates[0], wareHouseDates[1]);
        }

        queryWrapper.and(wq ->{
            wq.eq("a.`status`","0")
                    .or()
                    .eq("a.`status`","5");
        });

        IPage<WareHouseDto> iPage = basicMapper.wareHouseHistoryList(page, queryWrapper);
        //根据时间查询当前库存
        iPage.getRecords().stream().forEach(i->{
            //根据商品名称，物品类型，时间查当前库存
            String d = basicMapper.getWareHouseInfoByTime(i.getTradeName(),i.getWareHouseType(),i.getDateTest());
            i.setCurrentInventory(d);
        });
        //根据查询领用明细
        return iPage;
    }

    /**
     * 列表查询
     */
    public IPage<WareHouseDto> collectHistoryList(Page<WareHouseDto> page , WareHouseDto dto) throws Exception{
        QueryWrapper<WareHouseDto> queryWrapper = QueryWrapperGenerator.buildQueryCondition(dto, WareHouseDto.class);

        queryWrapper.eq("a.del_flag", "0");
        queryWrapper.eq("a.status", "5");
        if (StringUtils.isNotEmpty(dto.getTradeName())) {
            queryWrapper.eq("b.goods_name", dto.getTradeName());
        }

        if (StringUtils.isNotEmpty(dto.getCollectNo())) {
            queryWrapper.eq("a.collect_no", dto.getCollectNo());
        }

        String[] collectDates = dto.getCollectDates();
        if (collectDates != null) {

            queryWrapper.between("a.collect_date", collectDates[0], collectDates[1]);
        }
        IPage<WareHouseDto> iPage = basicMapper.collectHistoryList(page, queryWrapper);
        //根据时间查询当前库存
        iPage.getRecords().stream().forEach(i->{
            //根据商品名称，物品类型，时间查当前库存
            String d = basicMapper.getCollectInfoByTime(i.getGoodsName(),i.getCollectType(),i.getDateTest2());
            i.setCurrentInventory(d);
        });
        return iPage;
    }

    public String remove(String id) {
        // 删除基础信息表
        basicMapper.deleteById(id);
        // 删除详情列表 及对应附件信息
        List<WareHouseDetailed> detailedList = detailedMapper.getByBasicId(id);
        if (null != detailedList){
            detailedList.forEach(de->{
                //附件
                List<WorkAttachmentDto> fileList = detailedMapper.getByAttachmentId(de.getId());
                if ( null != fileList ){
                    fileList.forEach(f->{
                        ossServiceMapper.deleteById(f.getId());
                    });
                }
                detailedMapper.deleteById(de.getId());
            });
        }
        // 删除附件信息
        LambdaQueryWrapper<WorkAttachment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WorkAttachment::getAttachmentId, id);
        ossServiceMapper.delete(wrapper);
        //删除入库汇总表信息
//        List<WareHouseSummary> summaryList = summaryMapper.getInfoByBasicId(id);
//        summaryList.forEach(sum->{
//            summaryMapper.deleteById(sum.getId());
//        });
        return "操作成功";
    }

    public WareHouseDto findById(String id, String status) {
        WareHouseDto dto = new WareHouseDto();
        // 查询基础信息表
        WareHouseBasic info = basicMapper.selectById(id);
        BeanUtils.copyProperties(info, dto);
        dto.setCreateBy(info.getCreateById());
        // 查询入库详情数据，只包含没有被修改过的数据以及修改后的数据
        List<WareHouseDetailed> wareHouseList = detailedMapper.getByBasicId(id);
        // 审核页面或者查看详情页面要进这个判断，这里面会将被修改掉的数据也查出来
        if ("audit".equals(status) || "taskFormDetail".equals(status)) {
            List<WareHouseDetailed> wareList = new ArrayList<>();
            List<WareHouseDetailed> finalWareHouseList = detailedMapper.getByBasicIdAll(id);
            List<WareHouseDetailed> detailedList = wareHouseList; // 这里不copy一下会报错
            detailedList.stream().forEach(item2 -> {
                if (StringUtils.isBlank(item2.getSourceId())) {
                    wareList.add(item2); // 获取一直没有被修改过的数据
                }
            });
            finalWareHouseList.stream().forEach(item -> {
                if("2".equals(item.getUpFlag())) {
                    wareList.add(item); // 获取被删除的数据
                } else if ("1".equals(item.getUpFlag())) {
                    wareList.add(item); // 获取被修改的数据
                    detailedList.stream().forEach(item2 -> {
                        if (StringUtils.isNotBlank(item2.getSourceId())) {
                            if (item2.getSourceId().equals(item.getId())) {
                                wareList.add(item2); // 获取修改后的数据
                            }
                        }
                    });
                }
            });
            wareHouseList = new ArrayList<>(wareList); // 给 wareHouseList重新赋值
        }
        if (CollectionUtils.isNotEmpty(wareHouseList)){
            wareHouseList.forEach(detailed->{
                // 供应商查询
                if (StringUtils.isNotBlank(detailed.getIsSupplier()) && "2".equals(detailed.getIsSupplier()) &&
                        StringUtils.isNotBlank(detailed.getSupplierId())) {
                    MaterialSupplier materialSupplier = materialSupplierMapper.selectById(detailed.getSupplierId()); // 供应商信息
                    if (ObjectUtil.isNotEmpty(materialSupplier)) {
                        detailed.setSupplierName(materialSupplier.getName());
                    }
                }
                // 附件信息
                List<WorkAttachmentDto> acList = detailedMapper.getByAttachmentId(detailed.getId());
                if (CollectionUtils.isNotEmpty(acList)) {
                    for (WorkAttachmentDto i : acList) {
                        i.setCreateBy(SpringUtil.getBean ( IUserApi.class ).getById(i.getBy()));
                    }
                }
                detailed.setFileInfoLost(acList);
            });
        }
        //将采购详情数据查出
        List<MaterialDetailed> detailedList = new ArrayList<>();
        if (StringUtils.isNotEmpty(info.getPurchaseNo())) {
            MaterialBasic basic = materialBasicMapper.getInfoByPurchaseNo(info.getPurchaseNo());
            if (null != basic) {
                detailedList = materialDetailedMapper.getByBasicId(basic.getId());
            }
        }

        if (CollectionUtils.isNotEmpty(detailedList)){
            detailedList.forEach(detailed->{
                //附件信息
                List<WorkAttachmentDto> acList = materialDetailedMapper.getByAttachmentId(detailed.getId());
                if (CollectionUtils.isNotEmpty(acList)) {
                    for (WorkAttachmentDto i : acList) {
                        i.setCreateBy(SpringUtil.getBean ( IUserApi.class ).getById(i.getBy()));
                    }
                }
                detailed.setFileInfoLost(acList);
            });
        }
        dto.setDetailInfos(detailedList);
        dto.setWareHouse(wareHouseList);
        //附件信息
        List<WorkAttachmentDto> files = detailedMapper.getByAttachmentId(info.getId());
        if (CollectionUtils.isNotEmpty(files)) {
            for (WorkAttachmentDto i : files) {
                i.setCreateBy(SpringUtil.getBean ( IUserApi.class ).getById(i.getBy()));
            }
        }
        //根据经办人id查出经办人的名称
        String name = basicMapper.getUserNameByUserId(info.getHandledBy());
        dto.setHandledBy(name);
        dto.setHandledById(info.getHandledBy());
        dto.setFiles(files);
        return dto;
    }

    public String save(WareHouseDto dto) throws Exception{
        // 获取当前登录人信息
//        UserDTO userDTO = UserUtils.getCurrentUserDTO();
        UserDTO userDTO = SpringUtil.getBean ( IUserApi.class ).getByToken (TokenProvider.getCurrentToken ( ));
        if (StringUtils.isNotEmpty(dto.getId())) {
            return update(dto, userDTO);
        } else {
            return add(dto, userDTO);
        }
    }

    public String update(WareHouseDto dto, UserDTO userDTO) {
        if (StringUtils.isNotBlank(dto.getFunctionFlag())) {
            if ("start".equals(dto.getFunctionFlag())) { // 送审时执行
                // 添加当前修改申请人
                basicMapper.saveUpdateUser(dto.getId(),SpringUtil.getBean ( IUserApi.class ).getByToken (TokenProvider.getCurrentToken ( )).getId());
//                basicMapper.saveUpdateUser(dto.getId(),UserUtils.getCurrentUserDTO().getId());
                // 判断是否为第一次送审（目的是排除撤回后送审或者驳回后送审）
                List<WarehouseUpHi> warehouseUpHis = warehouseUpHiMapper.selectList(new LambdaQueryWrapper<WarehouseUpHi>()
                        .eq(WarehouseUpHi::getWarehouseId, dto.getId()).eq(WarehouseUpHi::getEndflag, "0"));
                if (CollectionUtil.isEmpty(warehouseUpHis)) { // 当前送审操作为第一次送审
                    // 将未修改的数据添加到历史数据表中
                    WareHouseDto byId = this.findById(dto.getId(),"false");
                    String jsonString = JSON.toJSONString(byId);
                    WarehouseUpHi warehouseUpHi = new WarehouseUpHi();
                    warehouseUpHi.setEndflag("0"); // endflag = 0 代表此数据为原数据，在回退数据的时候使用
                    warehouseUpHi.setJsonData(jsonString);
                    warehouseUpHi.setWarehouseId(dto.getId());
                    warehouseUpHiMapper.insert(warehouseUpHi);
                }
            }
            if ("agree".equals(dto.getFunctionFlag())) { // 审核通过时执行
                // 将历史数据表中的原始数据删除（end_flag = 0并且warehouse_id = 当前数据id）
                warehouseUpHiMapper.delete(new LambdaQueryWrapper<WarehouseUpHi>().eq(WarehouseUpHi::getEndflag,"0").eq(WarehouseUpHi::getWarehouseId,dto.getId()));
                WarehouseUpHi warehouseUpHi = new WarehouseUpHi();
                // 获取到当前审核页面的数据并存储到历史修改表中
                WareHouseDto byId = this.findById(dto.getId(),"audit");
                if (ObjectUtil.isNotEmpty(byId)) {
                    // 获取修改数据的商品名称、商品类型
                    if (CollectionUtil.isNotEmpty(byId.getWareHouse())){
                        List<WareHouseDetailed> updateData = byId.getWareHouse().stream().filter(i -> {
                            if ("1".equals(i.getUpFlag()) || "2".equals(i.getUpFlag())) {
                                return true;
                            }
                            return false;
                        }).collect(Collectors.toList());
                        List<String> updateTradeNameList = updateData.stream().map(WareHouseDetailed::getTradeName).collect(Collectors.toList());
                        if (CollectionUtil.isNotEmpty(updateTradeNameList)) {
                            //获取修改数据的商品名称
                            warehouseUpHi.setUpdateTradeName(String.join(",",updateTradeNameList));
                        }
                        List<String> updateTradeTypeList = updateData.stream().map(WareHouseDetailed::getWareHouseType).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
                        if (CollectionUtil.isNotEmpty(updateTradeTypeList)) {
                            //获取修改数据的商品类型
                            warehouseUpHi.setUpdateTradeType(String.join(",",updateTradeTypeList));
                        }
                    }
                    // 保存当前审核页面的数据到历史修改表
                    String jsonString = JSON.toJSONString(byId);
                    warehouseUpHi.setJsonData(jsonString);
                }
                // 获取数据修改申请人
                String updateUser = basicMapper.getUpdateUser(dto.getId());
                if (StringUtils.isNotBlank(updateUser)) {
                    warehouseUpHi.setUpdateUser(updateUser); // 历史修改表保存修改人
                    basicMapper.deleteUpdateUser(dto.getId()); // 删除数据修改申请人
                }
                warehouseUpHi.setEndflag("1"); // endflag = 1 代表当前数据为历史修改数据
                warehouseUpHi.setWarehouseId(dto.getId());
                warehouseUpHiMapper.insert(warehouseUpHi);
                // 修改基础信息
                WareHouseBasic info = new WareHouseBasic();
                BeanUtils.copyProperties(dto, info);
                info.setHandledBy(dto.getHandledById());
                basicMapper.updateById(info);
                // 把修改原因清空
                basicMapper.clearUpdateCause(dto.getId());
                // 入库详情修改
                List<WareHouseDetailed> wareHouseDetaileds = detailedMapper.selectList(new LambdaQueryWrapper<WareHouseDetailed>()
                        .eq(WareHouseDetailed::getBasicId,info.getId()));
                wareHouseDetaileds.stream().forEach(item -> {
                    if ("1".equals(item.getUpFlag()) || "2".equals(item.getUpFlag())) { // 将修改前的数据以及删除标记的数据删除
                        detailedMapper.deleteById(item.getId());
                    } else if ("0".equals(item.getUpFlag())) {
                        if (StringUtils.isNotBlank(item.getSourceId())) { // 将修改后数据的sourceId置空
                            detailedMapper.upSourceIdEmpty(item.getId()); // 根据入库详情id置空sourceId
                        }
                    }
                });
                return dto.getId();
            }
            if ("back".equals(dto.getFunctionFlag())) { // 撤回后取消修改、流程终止
                // 修改基础信息
                WareHouseBasic info = new WareHouseBasic();
                BeanUtils.copyProperties(dto, info);
                info.setHandledBy(dto.getHandledById());
                basicMapper.updateById(info);
                basicMapper.deleteUpdateUser(dto.getId()); // 删除数据修改申请人
                // 修改附件信息列表
                ossService.saveOrUpdateFileList(dto.getFiles(), dto.getId(),"ware_house_basic",TokenProvider.getCurrentToken ( ));
                // 入库详情修改
                // 物理删除此入库的全部入库关联的附件表数据，然后再新增附件。因为如果不物理删除，新增时会有主键冲突
                List<WareHouseDetailed> wareHouseDetaileds = detailedMapper.selectList(new QueryWrapper<WareHouseDetailed>().lambda().eq(WareHouseDetailed::getBasicId, dto.getId()));
                List<String> detailedIdList = wareHouseDetaileds.stream().map(WareHouseDetailed::getId).collect(Collectors.toList());
                detailedMapper.deleteFilesByIdList(detailedIdList);
                // 物理删除此入库的全部入库详情，然后再新增。因为如果不物理删除，新增时会有主键冲突
                detailedMapper.deleteByBasicId(dto.getId());
                if (CollectionUtils.isNotEmpty(dto.getWareHouse())) {
                    dto.getWareHouse().stream().forEach(item -> {
                        item.setWareHouseMan(item.getWareHouseManId());
                        item.setWareHouseType(item.getWareHouseTypeId());
                        detailedMapper.insert(item);
                        // 保存附件信息列表
                        ossService.saveOrUpdateFileList(item.getFileInfoLost(), item.getId(),"ware_house_detail",TokenProvider.getCurrentToken ( ));
                    });
                }
                // 删除送审时在历史修改表添加的数据
                warehouseUpHiMapper.delete(new QueryWrapper<WarehouseUpHi>().lambda()
                        .eq(WarehouseUpHi::getWarehouseId,dto.getId()).eq(WarehouseUpHi::getEndflag,"0"));
            }
        }

        // 修改基础信息
        WareHouseBasic info = new WareHouseBasic();
        BeanUtils.copyProperties(dto, info);
        info.setHandledBy(dto.getHandledById());
        basicMapper.updateById(info);

        // 入库详情修改
        if (CollectionUtils.isNotEmpty(dto.getWareHouse())) {
            // 获取前端删除的入库详情
            List<String> liveIds = dto.getWareHouse().stream().map(WareHouseDetailed::getId).collect(Collectors.toList());
            List<WareHouseDetailed> wareHouseDetaileds = detailedMapper.selectList(new LambdaQueryWrapper<WareHouseDetailed>()
                    .eq(WareHouseDetailed::getBasicId,info.getId()).notIn(WareHouseDetailed::getId, liveIds));
            wareHouseDetaileds.stream().forEach(d -> {
                if ("0".equals(d.getUpFlag())) {
                    d.setUpFlag("2"); // 已删除标记
                    dto.getWareHouse().add(d);
                }
            });
            dto.getWareHouse().stream().forEach(detailInfo -> {
                detailInfo.setWareHouseMan(detailInfo.getWareHouseManId());
                detailInfo.setWareHouseType(detailInfo.getWareHouseTypeId());
                detailInfo.setBasicId(dto.getId()); // 保存基础表信息主键值
                detailInfo.setTradeTotalPrice(dto.getWareHouseTotalPrice());
                if ("1".equals(detailInfo.getUpFlag())) { // ‘修改’标记数据
                    if(StringUtils.isBlank(detailInfo.getSourceId())) {
                        WareHouseDetailed ware = detailedMapper.selectById(detailInfo.getId());
                        boolean is = false;
                        // 判断是否有修改入库详情
                        if (judgmentEquals(detailInfo.getWareHouseMan(),ware.getWareHouseMan())) {
                            is = true;
                        } else if (judgmentEquals(detailInfo.getWareHouseType(),ware.getWareHouseType())) {
                            is = true;
                        } else if (judgmentEquals(detailInfo.getTradeName(),ware.getTradeName())) {
                            is = true;
                        } else if (judgmentEquals(detailInfo.getTradeNumber(),ware.getTradeNumber())) {
                            is = true;
                        } else if (judgmentEquals(detailInfo.getCompany(),ware.getCompany())) {
                            is = true;
                        } else if (judgmentEquals(detailInfo.getTradePrice(),ware.getTradePrice())) {
                            is = true;
                        } else if (judgmentEquals(detailInfo.getActualPrice(),ware.getActualPrice())) {
                            is = true;
                        } else if (judgmentEquals(detailInfo.getRemarks(),ware.getRemarks())) {
                            is = true;
                        } else if (checkSupplierIsChange(ware, detailInfo)) { // 判断供应商是否改变
                            is = true;
                        }
                        if (is) {
                            ware.setUpFlag("1");
                            detailedMapper.updateById(ware);
                            detailInfo.setSourceId(ware.getId());
                            detailInfo.setId(new String());
                            detailInfo.setUpFlag("0");
                            detailedMapper.insert(detailInfo);
                        }
                    }else{
                        detailInfo.setUpFlag("0");
                        detailedMapper.updateById(detailInfo);
                    }
                } else if ("2".equals(detailInfo.getUpFlag())) { // ‘删除’标记数据
                    if(StringUtils.isBlank(detailInfo.getSourceId())) {
                        detailedMapper.updateById(detailInfo);
                    }else{
                        WareHouseDetailed wareHouseDetailed = detailedMapper.selectById(detailInfo.getSourceId());
                        wareHouseDetailed.setUpFlag("2");
                        detailedMapper.updateById(wareHouseDetailed);
                        detailedMapper.deleteById(detailInfo.getId());
                    }
                }
                detailedMapper.updateById(detailInfo);
                // 修改附件信息列表
                ossService.saveOrUpdateFileList(detailInfo.getFileInfoLost(), detailInfo.getId(),"ware_house_detail",TokenProvider.getCurrentToken ( ));

            });
        } else {
            // 当入库详情列表为空时，所有数据打删除标记
            List<WareHouseDetailed> wareHouseDetaileds = detailedMapper.selectList(new LambdaQueryWrapper<WareHouseDetailed>().eq(WareHouseDetailed::getBasicId,info.getId()));
            wareHouseDetaileds.stream().forEach(d -> {
                d.setUpFlag("2"); // 已删除标记
                if(StringUtils.isBlank(d.getSourceId())) {
                    detailedMapper.updateById(d); // 据修改为 删除标记
                }else{
                    WareHouseDetailed wareHouseDetailed = detailedMapper.selectById(d.getSourceId());
                    wareHouseDetailed.setUpFlag("2");
                    detailedMapper.updateById(wareHouseDetailed); // 原数据修改为 删除标记
                    detailedMapper.deleteById(d.getId());
                }
            });
        }
        // 修改附件信息列表
        ossService.saveOrUpdateFileList(dto.getFiles(), dto.getId(),"ware_house_basic",TokenProvider.getCurrentToken ( ));

        return dto.getId();
    }

    // 判断两个字符串是否不相等  true不相等 false相等
    public boolean judgmentEquals(String a,String b) {
        if (StringUtils.isNotBlank(a) && StringUtils.isBlank(b)) { // a非空  b空
            return true;
        }
        if (StringUtils.isBlank(a) && StringUtils.isNotBlank(b)) { // a空  b非空
            return true;
        }
        if (StringUtils.isNotBlank(a) && StringUtils.isNotBlank(b) && !a.equals(b)) { // a非空  b非空  a、b不相等
            return true;
        }
        return false;
    }

    // 判断供应商是否改变
    public boolean checkSupplierIsChange(WareHouseDetailed oldData, WareHouseDetailed newData) {
        if (judgmentEquals(oldData.getSupplierId(),newData.getSupplierId())) {
            return true;
        }
        if (judgmentEquals(oldData.getSupplierName(),newData.getSupplierName())) {
            return true;
        }
        if (judgmentEquals(oldData.getIsSupplier(),newData.getIsSupplier())) {
            return true;
        }
        return false;
    }

    // 流程结束将全部修改的数据撤回到未修改
    public Map<String,String> backSourceData(String id){

        Map<String,String> map = new HashMap<>();
        map.put("result","error");
        String sourceData = warehouseUpHiMapper.getSourceData(id);
        if (StringUtils.isNotBlank(sourceData)) {
            WareHouseDto wareHouseDto = JSON.parseObject(sourceData, WareHouseDto.class);
            if (ObjectUtil.isNotEmpty(wareHouseDto)){
                wareHouseDto.setFunctionFlag("back");
                this.update(wareHouseDto,SpringUtil.getBean ( IUserApi.class ).getByToken (TokenProvider.getCurrentToken ( )));
//                this.update(wareHouseDto,UserUtils.getCurrentUserDTO());
                map.replace("result","success");
            }
        }
        return map;
    }

    public String add(WareHouseDto dto, UserDTO userDTO) throws Exception{
        // 生成id
        String id = UUID.randomUUID().toString().replace("-", "");
        // 生成编号
        String no = serialnumTplService.genSerialNum(userDTO.getCompanyDTO().getId(), dto.BIZ_CODE,TokenProvider.getCurrentToken());
        // 保存基础信息表信息
        WareHouseBasic info = new WareHouseBasic();
        BeanUtils.copyProperties(dto, info);
        info.setId(id);
//        info.setNo(no);
        info.setWareHouseNumber(no);
        info.setHandledBy(dto.getHandledById());
        info.setPurchaseNo(dto.getPurchaseNo());
        info.setCreateById(userDTO.getId());
        info.setCreateTime(new Date());
        info.setUpdateById(userDTO.getId());
        info.setUpdateTime(new Date());
        info.setDelFlag(0);
        basicMapper.insert(info);
        // 保存详情列表信息
        if (CollectionUtils.isNotEmpty(dto.getWareHouse())) {
            for (WareHouseDetailed detailed : dto.getWareHouse()) {
                // 生成id
                String detailId = UUID.randomUUID().toString().replace("-", "");
                detailed.setWareHouseMan(detailed.getWareHouseManId());
                detailed.setId(detailId);
                detailed.setCreateById(userDTO.getId());
                detailed.setCreateTime(new Date());
                detailed.setUpdateById(userDTO.getId());
                detailed.setUpdateTime(new Date());
                detailed.setDelFlag(0);
                detailed.setCompany(dto.getCompany());
                detailed.setRemarks(dto.getRemarks());
                detailed.setActualPrice(dto.getActualPrice());
                detailed.setWareHouseType(detailed.getWareHouseTypeId());
                // 保存基础表信息主键值
                detailed.setBasicId(id);
                detailed.setTradeTotalPrice(dto.getWareHouseTotalPrice());
                detailed.setUpFlag("0");
                if (StringUtils.isNotBlank(detailed.getWareHouseType()) && StringUtils.isNotBlank(detailed.getTradeName())) {
                    // 根据商品名称和入库类型查询 警告数量、警告标记
                    List<WareHouseDto> byTypeAndTradeName = wareHouseBasicMapper.getByTypeAndTradeName(detailed.getTradeName(), detailed.getWareHouseType());
                    // 如果存在，则将当前新增数据的 警告数量、警告标记 赋值为查询到的值
                    if (CollectionUtil.isNotEmpty(byTypeAndTradeName)) {
                        detailed.setWarnNum(byTypeAndTradeName.get(0).getWarnNum()); // 提醒数量
                        detailed.setWarnFlag(byTypeAndTradeName.get(0).getWarnFlag()); // 提醒标记
                    }
                }
                //获取该商品对应的库存数据
                WareHouseDto wareHouseDto = wareHouseBasicMapper.getByTypeAndGoodsName(detailed.getTradeName(), detailed.getWareHouseTypeId());
                //设置当前库存
                if (null == wareHouseDto){
                    detailed.setCurrentInventory("");
                } else {
//                        Double num1 = Double.parseDouble(detailInfo.getTradeNumber());
//                        Double num2 = Double.parseDouble(wareHouseDto.getTradeNumber());
//                        String sum = num1 + num2 + "";
                    detailed.setCurrentInventory(wareHouseDto.getTradeNumber());
                }
                detailedMapper.insert(detailed);
                //保存详情列表附件信息
                if (CollectionUtils.isNotEmpty(detailed.getFileInfoLost())){
                    basicService.saveFiles(detailed.getFileInfoLost(), userDTO, detailId);
                }
                //将入库详情商品信息汇总处理
                //根据商品名称及入库类型查是否有相关数据
//                WareHouseSummary summary = summaryMapper.getInfoByTradeName(detailed.getTradeName(),detailed.getWareHouseType());;
//                if (null != summary) {
//                    String num = Double.valueOf(detailed.getTradeNumber())
//                            + Double.valueOf(summary.getTradeNumber()) + "";
//                    summary.setTradeNumber(num);
//                    summaryMapper.updateById(summary);
//                } else {
//                    summary = new WareHouseSummary();
//                    // 生成id
//                    String summaryId = UUID.randomUUID().toString().replace("-", "");
//                    summary.setDetailedId(detailed.getId());
//                    summary.setId(summaryId);
//                    summary.setCreateBy(userDTO.getId());
//                    summary.setCreateDate(new Date());
//                    summary.setUpdateBy(userDTO.getId());
//                    summary.setUpdateDate(new Date());
//                    summary.setDelFlag(0);
//                    summary.setWareHouseType(detailed.getWareHouseType());
//                    summary.setTradeName(detailed.getTradeName());
//                    summary.setTradeNumber(detailed.getTradeNumber());
//                    summaryMapper.insert(summary);
//                }
            }
        }
        // 保存附件列表信息
        if (CollectionUtils.isNotEmpty(dto.getFiles())) {
            basicService.saveFiles(dto.getFiles(), userDTO, id);

        }

        // 将新增的数据保存到历史数据表中
        WareHouseDto byId = this.findById(info.getId(),"false");
        String jsonString = JSON.toJSONString(byId);
        WarehouseUpHi warehouseUpHi = new WarehouseUpHi();
        warehouseUpHi.setUpdateUser(byId.getCreateBy());
        warehouseUpHi.setWarehouseId(byId.getId());
        warehouseUpHi.setEndflag("2");
        warehouseUpHi.setJsonData(jsonString);
        warehouseUpHiMapper.insert(warehouseUpHi);

        return id;
    }

    /**
     * 列表查询
     */
    public IPage<WareHouseDto> list(Page<WareHouseDto> page , WareHouseDto dto) throws Exception{
        QueryWrapper<WareHouseDto> queryWrapper = QueryWrapperGenerator.buildQueryCondition(dto, WareHouseDto.class);

        queryWrapper.eq("a.del_flag", "0");
        if (StringUtils.isNotEmpty(dto.getWareHouseNumber())) {
            queryWrapper.like("a.ware_house_number", dto.getWareHouseNumber());
        }
        if (StringUtils.isNotEmpty(dto.getWareHouseName())) {
            queryWrapper.like("a.ware_house_name", dto.getWareHouseName());
        }
        if (StringUtils.isNotEmpty(dto.getHandledBy())) {
            queryWrapper.like("sy.id", dto.getHandledBy());
        }
        if (StringUtils.isNotEmpty(dto.getHandledByOffice())) {
            queryWrapper.like("a.handled_by_office", dto.getHandledByOffice());
        }
        if (StringUtils.isNotEmpty(dto.getStatus())) {
            queryWrapper.like("a.status", dto.getStatus());
        }
        if (StringUtils.isNotEmpty(dto.getPurchaseId())) {
            queryWrapper.eq("b.id", dto.getPurchaseId());
        }
        if (StringUtils.isNotEmpty(dto.getSupplierId())) {
            List<WareHouseDetailed> wareHouseDetaileds = detailedMapper.selectList(new LambdaQueryWrapper<WareHouseDetailed>().eq(WareHouseDetailed::getSupplierId, dto.getSupplierId()));
            if (CollectionUtil.isNotEmpty(wareHouseDetaileds)) {
                List<String> containsIds = wareHouseDetaileds.stream().map(WareHouseDetailed::getBasicId).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(containsIds)) {
                    queryWrapper.in("a.id", containsIds);
                } else {
                    return new Page<>();
                }
            } else {
                return new Page<>();
            }
        }
        // 入库时间
        String[] contractDates = dto.getWareHouseDates();
        if (contractDates != null) {
            queryWrapper.between("a.ware_house_date", contractDates[0], contractDates[1]);
        }
        if (dto.getStatusTwo() != null) {
            queryWrapper.and(wq ->{
                wq.eq("a.`status`",dto.getStatusTwo()[0])
                        .or()
                        .eq("a.`status`",dto.getStatusTwo()[1]);
            });
        }
        IPage<WareHouseDto> list = basicMapper.findList(page, queryWrapper);
        list.getRecords().forEach(item -> {
            // 入库 修改申请
            if (StringUtils.isNotBlank(item.getTaskId()) && StringUtils.isNotBlank(item.getStatus())) {
                if ("2".equals(item.getStatus())) { // “审核中”的数据要获取数据审核人
                    item.setAuditUserIds(flowTaskService.getTaskAuditUsers(item.getTaskId()));  // 获取数据审核人
                }
            }
        });
        return list;
    }

    /**
     * 列表查询
     */
    public IPage<WareHouseDto> summaryList2(Page<WareHouseDto> page , WareHouseDto dto) throws Exception{
        QueryWrapper<WareHouseDto> queryWrapper = QueryWrapperGenerator.buildQueryCondition(dto, WareHouseDto.class);

        queryWrapper.eq("a.del_flag", "0");
        // 库存数量小于等于0的不展示
//        queryWrapper.gt("a.trade_number - b.collect_number", "0");
//        if (StringUtils.isNotEmpty(dto.getWareHouseNumber())) {
//            queryWrapper.like("c.ware_house_number", dto.getWareHouseNumber());
//        }
        if (StringUtils.isNotEmpty(dto.getTradeName())) {
            queryWrapper.like("a.trade_name", dto.getTradeName());
        }
        if (StringUtils.isNotEmpty(dto.getBasicId())) {
            queryWrapper.eq("b.mmcId", dto.getBasicId());
        }
//        queryWrapper.and(wq ->{
//            wq.eq("bas.`status`","0")
//                    .or()
//                    .eq("bas.`status`","5");
//        });

        //入库类型
        if (StringUtils.isNotEmpty(dto.getWareHouseType())) {
            queryWrapper.eq("c.id", dto.getWareHouseType());
        }
        IPage<WareHouseDto> iPage = basicMapper.summaryList2(page, queryWrapper);
        iPage.getRecords().stream().forEach(i->{
            //根据领用类型及领用物品名称查领用数量
            String collectNum = basicMapper.getCollectNumByType(i.getWareHouseType(),i.getTradeName());
            i.setBorrowNumber(collectNum);
            BigDecimal decimal1 = new BigDecimal(i.getAllNumber());
            BigDecimal decimal2 = new BigDecimal(i.getBorrowNumber());

            i.setTradeNumber(decimal1.subtract(decimal2).toString());
        });


        return basicMapper.summaryList2(page, queryWrapper);
    }

    /**
     * 列表查询
     */
    public IPage<WareHouseDto> summaryList(Page<WareHouseDto> page , WareHouseDto dto) throws Exception{
        QueryWrapper<WareHouseDto> queryWrapper = QueryWrapperGenerator.buildQueryCondition(dto, WareHouseDto.class);

        queryWrapper.eq("a.del_flag", "0");
        // 库存数量小于等于0的不展示
//        queryWrapper.gt("a.trade_number - b.collect_number", "0");
//        if (StringUtils.isNotEmpty(dto.getWareHouseNumber())) {
//            queryWrapper.like("c.ware_house_number", dto.getWareHouseNumber());
//        }
        if (StringUtils.isNotEmpty(dto.getTradeName())) {
            queryWrapper.like("a.trade_name", dto.getTradeName());
        }
        queryWrapper.and(wq ->{
            wq.eq("bas.`status`","0")
                    .or()
                    .eq("bas.`status`","5");
        });
//        if (StringUtils.isNotEmpty(dto.getWareHouseMan())) {
//            queryWrapper.like("a.ware_house_man", dto.getWareHouseMan());
//        }
//        if (StringUtils.isNotEmpty(dto.getWareHouseManOffice())) {
//            queryWrapper.like("so.id", dto.getWareHouseManOffice());
//        }

        //入库类型
        if (StringUtils.isNotEmpty(dto.getWareHouseType())) {
            queryWrapper.eq("c.id", dto.getWareHouseType());
        }

        // 入库时间
//        String[] contractDates = dto.getWareHouseDates();
//        if (contractDates != null) {
//
//            queryWrapper.between("c.ware_house_date", contractDates[0], contractDates[1]);
//        }
        if (StringUtils.isNotEmpty(dto.getSupplierId())) {
            List<WareHouseDetailed> wareHouseDetaileds = detailedMapper.selectList(new LambdaQueryWrapper<WareHouseDetailed>().eq(WareHouseDetailed::getSupplierId, dto.getSupplierId()));
            if (CollectionUtil.isNotEmpty(wareHouseDetaileds)) {
                List<String> containsIds = wareHouseDetaileds.stream().map(WareHouseDetailed::getId).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(containsIds)) {
                    queryWrapper.in("a.id", containsIds);
                } else {
                    return new Page<>();
                }
            } else {
                return new Page<>();
            }
        }
        IPage<WareHouseDto> wareHouseDtoIPage = basicMapper.summaryList(page, queryWrapper);
        wareHouseDtoIPage.getRecords().forEach(item -> {
            // 将小数点后无效的0删除
            // 总量  格式化
            if (StringUtils.isNotBlank(item.getAllNumber())) {
                String s = convertByBigDecimal(item.getAllNumber());
                item.setAllNumber(s);
            }
            //领用量  格式化
            if (StringUtils.isNotBlank(item.getBorrowNumber())) {
                String s = convertByBigDecimal(item.getBorrowNumber());
                item.setBorrowNumber(s);
            }
            //剩余量  格式化
            if (StringUtils.isNotBlank(item.getTradeNumber())) {
                String s = convertByBigDecimal(item.getTradeNumber());
                item.setTradeNumber(s);
            }
            //提醒数量  格式化
            if (StringUtils.isNotBlank(item.getWarnNum())) {
                String s = convertByBigDecimal(item.getWarnNum());
                item.setWarnNum(s);
            }
        });
        return wareHouseDtoIPage;
    }
    // 去除小数点后无效的0
    public String convertByBigDecimal(String value) {
        BigDecimal bigDecimal = new BigDecimal(value);
        BigDecimal res = bigDecimal.stripTrailingZeros();
        return res.toPlainString();
    }

    public String findRequestId(String purchaseNo) {
        return basicMapper.findRequestId(purchaseNo);
    }

    public String updateStatusById(WareHouseDto dto) {
        WareHouseBasic wareHouseBasic = new WareHouseBasic();
        BeanUtils.copyProperties(dto,wareHouseBasic);
        basicMapper.update(wareHouseBasic, new QueryWrapper<WareHouseBasic>().lambda().eq(WareHouseBasic::getId, wareHouseBasic.getId()));
        return "操作成功";
    }

    // 根据入库表id查询其全部历史修改数据
    public List<WarehouseUpHi> findHiById(String warehouseId) {
        return warehouseUpHiMapper.findHiById(warehouseId);
    }

    // 根据历史表id查询历史表数据
    public WareHouseDto findHiByHiId(String hiId) {
        WareHouseDto wareHouseDto = new WareHouseDto();
        WarehouseUpHi hiByHiId = warehouseUpHiMapper.findHiByHiId(hiId); // 根据历史表id查询历史表数据
        if (ObjectUtil.isNotEmpty(hiByHiId) && StringUtils.isNotBlank(hiByHiId.getJsonData())) {
            wareHouseDto = JSON.parseObject(hiByHiId.getJsonData(), WareHouseDto.class); // json字符串解析为java对象
            if (ObjectUtil.isNotEmpty(wareHouseDto)) {
                // 入库详情中的附件数据获取。
                // 在这里要重新获取一下入库详情附件的原因是，json字符串中的附件createBy值存储不正确，所以重新获取一下
                if(CollectionUtil.isNotEmpty(wareHouseDto.getWareHouse())) {
                    wareHouseDto.getWareHouse().forEach(detailed->{
                        List<WorkAttachmentDto> acList = detailedMapper.getByAttachmentId(detailed.getId());
                        if (CollectionUtils.isNotEmpty(acList)) {
                            for (WorkAttachmentDto i : acList) {
                                i.setCreateBy(SpringUtil.getBean ( IUserApi.class ).getById(i.getBy()));
                            }
                        }
                        detailed.setFileInfoLost(acList);
                    });
                }
                // 入库附件同上
                if(CollectionUtil.isNotEmpty(wareHouseDto.getFiles())) {
                    wareHouseDto.getFiles().forEach(file->{
                        file.setCreateBy(SpringUtil.getBean ( IUserApi.class ).getById(file.getBy()));
                    });
                }
            }

        }
        return wareHouseDto;
    }

    // 根据入库表id查询最近的一个修改历史
    public WareHouseDto findLastHiByid(String warehouseId) {
        WareHouseDto wareHouseDto = new WareHouseDto();
        WarehouseUpHi hiByHiId = warehouseUpHiMapper.findLastHiByid(warehouseId); // 根据入库表id查询最近的一个修改历史
        if (ObjectUtil.isNotEmpty(hiByHiId) && StringUtils.isNotBlank(hiByHiId.getJsonData())) {
            wareHouseDto = JSON.parseObject(hiByHiId.getJsonData(), WareHouseDto.class); // json字符串解析为java对象
            if (ObjectUtil.isNotEmpty(wareHouseDto)) {
                // 入库详情中的附件数据获取。
                // 在这里要重新获取一下入库详情附件的原因是，json字符串中的附件createBy值存储不正确，所以重新获取一下
                if(CollectionUtil.isNotEmpty(wareHouseDto.getWareHouse())) {
                    wareHouseDto.getWareHouse().forEach(detailed->{
                        List<WorkAttachmentDto> acList = detailedMapper.getByAttachmentId(detailed.getId());
                        if (CollectionUtils.isNotEmpty(acList)) {
                            for (WorkAttachmentDto i : acList) {
                                i.setCreateBy(SpringUtil.getBean ( IUserApi.class ).getById(i.getBy()));
                            }
                        }
                        detailed.setFileInfoLost(acList);
                    });
                }
                // 入库附件同上
                if(CollectionUtil.isNotEmpty(wareHouseDto.getFiles())) {
                    wareHouseDto.getFiles().forEach(file->{
                        file.setCreateBy(SpringUtil.getBean ( IUserApi.class ).getById(file.getBy()));
                    });
                }
            }
        }
        return wareHouseDto;
    }

    // 根据商品名称和入库类型修改提醒状态
    public ResponseEntity updateWarnFlagByTradeNameAndType(WareHouseDto wareHouseDto) {
        if (ObjectUtil.isNotEmpty(wareHouseDto.getTradeName()) && StringUtils.isNotBlank(wareHouseDto.getWareHouseType())) {
            // 查询此数据的状态
            List<WareHouseDto> wareHouseDtoList = basicMapper.getByTypeAndTradeName(wareHouseDto.getTradeName(),wareHouseDto.getWareHouseType());
            if (CollectionUtil.isNotEmpty(wareHouseDtoList)) {
                if ("1".equals(wareHouseDtoList.get(0).getWarnFlag())) { // 当前状态为启用
                    basicMapper.updateWarnFlagByTradeNameAndType("0", wareHouseDto.getTradeName(), wareHouseDto.getWareHouseType()); // 设置为停用
                    return ResponseEntity.ok("修改提醒状态成功");
                } else if ("0".equals(wareHouseDtoList.get(0).getWarnFlag())) { // 当前状态为停用
                    basicMapper.updateWarnFlagByTradeNameAndType("1", wareHouseDto.getTradeName(), wareHouseDto.getWareHouseType()); // 设置为启用
                    return ResponseEntity.ok("修改提醒状态成功");
                }
            }
        }
        return ResponseEntity.badRequest().body("修改提醒状态失败");
    }


    // 根据商品名称和入库类型修改提醒数量
    public ResponseEntity updateWarnNumByTradeNameAndType(WareHouseDto wareHouseDto) {
        if (ObjectUtil.isNotEmpty(wareHouseDto.getTradeName()) && StringUtils.isNotBlank(wareHouseDto.getWareHouseType())) {
            if (StringUtils.isNotBlank(wareHouseDto.getWarnNum())) {
                // 查询此数据的状态
                List<WareHouseDto> wareHouseDtoList = basicMapper.getByTypeAndTradeName(wareHouseDto.getTradeName(),wareHouseDto.getWareHouseType());
                if (CollectionUtil.isNotEmpty(wareHouseDtoList)) {
                    if (wareHouseDto.getWarnNum().equals(wareHouseDtoList.get(0).getWarnNum())) { // 如果查询到的提醒数量与修改的提醒数量相同则直接返回修改成功
                        return ResponseEntity.ok("修改提醒数量成功");
                    } else { // 如果查询到的提醒数量与修改的提醒数量不相同则修改提醒数量
                        basicMapper.updateWarnNumByTradeNameAndType(wareHouseDto.getWarnNum(), wareHouseDto.getTradeName(), wareHouseDto.getWareHouseType()); // 修改提醒数量
                        return ResponseEntity.ok("修改提醒数量成功");
                    }
                }
            }
        }
        return ResponseEntity.badRequest().body("修改提醒数量失败");
    }

    public void saveTradeName (WareHouseDto wareHouseDto) {
        if (ObjectUtil.isNotEmpty(wareHouseDto)) {
            if (StringUtils.isNotBlank(wareHouseDto.getOldTradeName()) && StringUtils.isNotBlank(wareHouseDto.getTradeName()) && StringUtils.isNotBlank(wareHouseDto.getWareHouseType())) {
                // 修改入库详情 商品名称
                detailedMapper.saveTradeName(wareHouseDto.getOldTradeName(), wareHouseDto.getTradeName(), wareHouseDto.getWareHouseType());
                // 修改领用详情 商品名称
                detailedMapper.saveGoodsName(wareHouseDto.getOldTradeName(), wareHouseDto.getTradeName(), wareHouseDto.getWareHouseType());
            }
        }
    }

    public List<WareHouseDetailed> findTradeByTypeId (String typeId) {
        if (StringUtils.isNotBlank(typeId)) {
            List<WareHouseDetailed> wareHouseDetaileds = detailedMapper.getByTypeId(typeId);
            return wareHouseDetaileds;
        } else {
            return new ArrayList<>();
        }
    }
}
