package com.yeejoin.equipmanage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.equipmanage.common.entity.*;
import com.yeejoin.equipmanage.common.entity.vo.EquipmentOnCarAppVO;
import com.yeejoin.equipmanage.common.enums.*;
import com.yeejoin.equipmanage.common.exception.BaseException;
import com.yeejoin.equipmanage.common.utils.StringUtil;
import com.yeejoin.equipmanage.fegin.IdxFeign;
import com.yeejoin.equipmanage.mapper.CarMapper;
import com.yeejoin.equipmanage.mapper.EquipmentOnCarMapper;
import com.yeejoin.equipmanage.mapper.OrgUsrMapper;
import com.yeejoin.equipmanage.mapper.ScrapMapper;
import com.yeejoin.equipmanage.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

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

/**
 * 服务实现类
 *
 * @author wujiang
 * @date 2020-07-07
 */
@Service
public class ScrapServiceImpl extends ServiceImpl<ScrapMapper, Scrap> implements IScrapService {

    @Autowired
    private IScrapService scrapService;
    @Autowired
    private IScrapDetailService scrapDetailService;
    @Autowired
    private IStockDetailService stockDetailService;
    @Autowired
    private IJournalService journalService;
    @Autowired
    private INoticeService noticeService;
    @Autowired
    private IStockBillService stockBillService;
    @Autowired
    private ICarService carService;
    @Autowired
    private ISystemDicService iSystemDicService;
    @Autowired
    private CarMapper carMapper;
    @Autowired
    private ScrapMapper scrapMapper;

    @Autowired
    private EquipmentOnCarMapper equipmentOnCarMapper;

    @Autowired
    private IdxFeign idxFeign;

    @Autowired
    private OrgUsrMapper orgUsrMapper;

    @Override
    public Scrap create(List<ScrapDetail> list, String type, AgencyUserModel agencyUserModel) {
        this.scrapCheck(type, list);
        Scrap scrap = new Scrap();
        scrap.setBillCode(stockBillService.generateQrCode("BF"));
        scrap.setBillType(type);
        scrap.setStatus(TaskStatusEnum.INPROGRESS.getCode());
        scrap.setUserId(Long.valueOf(agencyUserModel.getUserId()));
        scrap.setCreatorName(agencyUserModel.getRealName());
        scrapService.save(scrap);
		for (ScrapDetail scrapDetail : list) {
			if (BillContentEnum.CL.getCode().equals(type)) {
				scrapDetail.setAmount(1.0);
			}
			scrapDetail.setScrapId(scrap.getId());
		}
		scrapDetailService.saveBatch(list);
        return scrap;
    }

    private void scrapCheck(String type, List<ScrapDetail> list) {
        if (BillContentEnum.CL.getCode().equals(type)) {
			for (ScrapDetail scrapDetail : list) {
				List<EquipmentOnCarAppVO> equipmentOnCarAppVOS = carMapper.selectEquipmentOnCarAppList(scrapDetail.getCarId());
				if (equipmentOnCarAppVOS.size() > 0) {
					throw new BaseException("有车载装备的车辆不能报废，请先卸载装备！");
				}
				Car car = carMapper.selectById(scrapDetail.getCarId());
				if (car.getCarState().equals(CarStatusEnum.BF.getCode())) {
					throw new BaseException("不能重复报废");
				}
			}
        } else {
            //1.增加校验，车载准备需要先卸载才能报废
			for (ScrapDetail scrapDetail : list) {
				StockDetail stockDetail = stockDetailService.getById(scrapDetail.getStockDetailId());
				if (stockDetail == null) {
					throw new BaseException("查询库存失败，请联系管理员");
				}
				if (EquipStatusEnum.ONCAR.getCode().toString().equals(stockDetail.getStatus())) {
					throw new BaseException("请先在手机端卸载装备再进行报废");
				}
			}
            //增加校验，装备不能重复报废
			for (ScrapDetail scrapDetail : list) {
				StockDetail stockDetail = stockDetailService.getById(scrapDetail.getStockDetailId());
				if (EquipStatusEnum.SCRAP.getCode().toString().equals(stockDetail.getStatus())) {
					throw new BaseException("不能重复报废");
				}
			}
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Scrap exec(Scrap scrap) {
		scrap = scrapService.getById(scrap.getId());
    	scrap.setStatus(TaskStatusEnum.COMPLETED.getCode());
        QueryWrapper<ScrapDetail> scrapDetailQueryWrapper = new QueryWrapper<>();
        scrapDetailQueryWrapper.eq("scrap_id", scrap.getId());
        List<ScrapDetail> scrapDetails = scrapDetailService.list(scrapDetailQueryWrapper);
        List<StockDetail> stockDetailIds = new ArrayList<>();
        //前置校验
        this.scrapCheck(scrap.getBillType(), scrapDetails);
        scrapDetails.forEach(x -> {
            StockDetail stockDetail = new StockDetail();
            stockDetail.setId(x.getStockDetailId());
            stockDetail.setStatus("7");
            stockDetail.setUpdateDate(new Date());
            stockDetailIds.add(stockDetail);
        });
        //修改库存状态
        stockDetailService.updateBatchById(stockDetailIds);
        scrapService.updateById(scrap);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("scrap_id", scrap.getId());
        List<ScrapDetail> list = (List<ScrapDetail>) scrapDetailService.listByMap(map);
		// 装备
        if (BillContentEnum.ZB.getCode().equals(scrap.getBillType())) {
            // wl_journal表
            saveEquipJournal(list, JournalTypeEnum.BF);
            updateEquipStatus(list, EquipStatusEnum.SCRAP);
        }
        // 灭火药剂
        else if (BillContentEnum.MHYJ.getCode().equals(scrap.getBillType())) {
        	//校验要报废的灭火药剂库存是否够用
        	this.checkAmount(list);
            saveEquipJournal(list, JournalTypeEnum.BF);
            updateExtinguishingStatus(list, EquipStatusEnum.SCRAP);
        }
        // 车辆
        else {
            // wl_journal表
            saveCarJournal(list, JournalTypeEnum.BF);
            updateCarStatus(list, CarStatusEnum.BF);
        }

        // wl_notice表
        noticeService.saveEquipNotice(NoticeEnum.BF, scrap.getId(), scrap.getBillCode());
        return scrap;
    }

	private void checkAmount(List<ScrapDetail> list) {
		for (ScrapDetail scrapDetail : list) {
			StockDetail stockDetail = stockDetailService.getById(scrapDetail.getStockDetailId());
			//1.按照stockDetailId 分组，求和来校验要报废的数量是否超出数据库已有数量
			Map<Long,List<ScrapDetail>> map = list.stream().collect(Collectors.groupingBy(ScrapDetail::getStockDetailId));
			if(map.get(stockDetail.getId()) != null){
				double totalWaitSum = map.get(stockDetail.getId()).stream().mapToDouble(ScrapDetail::getAmount).sum();
				BigDecimal total = BigDecimal.valueOf(totalWaitSum);
				BigDecimal db = BigDecimal.valueOf(stockDetail.getAmount());
				if(total.compareTo(db) > 0){
					throw new BaseException("报废的灭火药剂总数量大于已有库存");
				}
			}
		}
	}


	private void saveEquipJournal(List<ScrapDetail> list, JournalTypeEnum journalTypeEnum) {
        List<Journal> journalList = new ArrayList<Journal>();
        for (ScrapDetail scrapDetail : list) {
            Journal journal = new Journal();
            StockDetail stockDetail = stockDetailService.getById(scrapDetail.getStockDetailId());
            journal.setAmount(stockDetail.getAmount());
            journal.setEquipmentDetailId(stockDetail.getEquipmentDetailId());
            journal.setStockDetailId(stockDetail.getId());
            journal.setRemark(journalTypeEnum.getName());
            journal.setWarehouseStructureId(stockDetail.getWarehouseStructureId());
            journal.setState(journalTypeEnum.getCode());
            journalList.add(journal);
        }
        journalService.saveBatch(journalList);
    }

    private void updateEquipStatus(List<ScrapDetail> list, EquipStatusEnum equipStatusEnum) {
        List<StockDetail> stockDetailList = new ArrayList<StockDetail>();
        for (ScrapDetail scrapDetail : list) {
            StockDetail stockDetail = stockDetailService.getById(scrapDetail.getStockDetailId());
            stockDetail.setStatus(equipStatusEnum.getCode().toString());
			//更新库存，之前在新增报废时减库存，现调整为报废时再减库存,
            BigDecimal stockAmount = new BigDecimal(stockDetail.getAmount());
			BigDecimal scrapAmount = new BigDecimal(scrapDetail.getAmount());
//			stockDetail.setAmount(stockAmount.subtract(scrapAmount).doubleValue());
            stockDetail.setAmount(stockAmount.doubleValue());
            stockDetailList.add(stockDetail);

            // 装备报废时消码为绿码
            idxFeign.handleEquipScrapWhenExpired(String.valueOf(stockDetail.getEquipmentSpecificId()));

        }
        stockDetailService.updateBatchById(stockDetailList);
    }


    private void updateExtinguishingStatus(List<ScrapDetail> list, EquipStatusEnum equipStatusEnum) {
        List<StockDetail> stockDetailList = new ArrayList<StockDetail>();
        List<StockDetail> newStockDetailList = new ArrayList<StockDetail>();
        for (ScrapDetail scrapDetail : list) {
            StockDetail stockDetail = stockDetailService.getById(scrapDetail.getStockDetailId());
            stockDetail.setAmount(stockDetail.getAmount() - scrapDetail.getAmount());
			//灭火药剂更新原来的流水状态库存状态
            stockDetail.setStatus(EquipStatusEnum.REPERTORY.getCode().toString());
            StockDetail newStockDetail = new StockDetail();
            BeanUtils.copyProperties(stockDetail, newStockDetail);
            //插入一条新的为报废状态
            newStockDetail.setId(null);
            newStockDetail.setAmount(scrapDetail.getAmount());
            newStockDetail.setStatus(equipStatusEnum.getCode().toString());
            newStockDetailList.add(newStockDetail);
            stockDetailList.add(stockDetail);
        }
        stockDetailService.updateBatchById(stockDetailList);
        // 灭火药剂新增报废库存明细
        if (!newStockDetailList.isEmpty()) {
            stockDetailService.saveBatch(newStockDetailList);
        }
    }

    private void saveCarJournal(List<ScrapDetail> list, JournalTypeEnum journalTypeEnum) {
        List<Journal> journalList = new ArrayList<Journal>();
        for (ScrapDetail scrapDetail : list) {
            Journal journal = new Journal();
            Car car = carService.getById(scrapDetail.getCarId());
            journal.setAmount(1.0);
            journal.setCarId(car.getId());
            journal.setRemark(journalTypeEnum.getName());
            journal.setState(journalTypeEnum.getCode());
            journalList.add(journal);
        }
        journalService.saveBatch(journalList);
    }

    private void updateCarStatus(List<ScrapDetail> list, CarStatusEnum carStatusEnum) {
        List<Car> carList = new ArrayList<Car>();
        for (ScrapDetail scrapDetail : list) {
            Car car = carService.getById(scrapDetail.getCarId());
            car.setCarState(carStatusEnum.getCode());
            carList.add(car);
        }
        carService.updateBatchById(carList);
    }

    @Override
    public IPage<Scrap> pageList(Page<Scrap> pageBean, QueryWrapper<Scrap> queryWrapper) {
        IPage<Scrap> page = page(pageBean, queryWrapper);
        for (Scrap scrap : page.getRecords()) {
            String type = scrap.getBillType();
            String img = scrapMapper.getImgById(scrap.getId(), type);
            if (img != null && !"".equals(img)) {
                scrap.setImg(img);
            }
            List<Map<String, Object>> list = scrapDetailService.geteqTypeAndAmount(scrap.getId());
            if (0 < list().size()) {
                for (Map<String, Object> x : list) {
                    String amount = x.get("amount").toString();
                    String eqType = x.get("eqType").toString();
                    String unitName = x.get("unitName").toString();
                    String re = amount + unitName;
                    if (StringUtil.isNotEmpty(eqType) && !"4".equals(eqType)) {
                        re = amount.split("\\.")[0] + unitName;
                    }
                    scrap.setDetailCount(re);
                }
            }
//			scrap.setDetailCount(
//					scrapDetailService.getOne(new QueryWrapper<ScrapDetail>().eq("scrap_id", scrap.getId())).getAmount());
        }
        return page;
    }

    @Override
    public List<SystemDic> reason() {
        return iSystemDicService.list(new QueryWrapper<SystemDic>().eq("type", "ScrapReason"));
    }

    @Override
    public void scrapOnCar(Long id) {
        // 由于目前下发需求机场项目没有生命周期管理，所以此处没有维护台账及报废单据等信息
        StockDetail stockDetail = stockDetailService.getById(id);
        QueryWrapper<EquipmentOnCar> queryWrapper = new QueryWrapper<>();
        equipmentOnCarMapper.delete(queryWrapper.eq("stock_detail_id", id));
        stockDetail.setAmount(stockDetail.getAmount() + 1.0);
        stockDetail.setStatus(String.valueOf(EquipStatusEnum.SCRAP.getCode()));
        stockDetailService.updateById(stockDetail);
    }

    @Override
    @Transactional
    public void scrapOnPerson(Map<String, Object> map, AgencyUserModel agencyUserModel) {
        Long id = Long.valueOf(map.get("stockDetailId").toString());
        double amount = Double.parseDouble(map.get("amount").toString());
        StockDetail stockDetail = stockDetailService.getById(id);
        if (null == stockDetail) {
            throw new RuntimeException("id为"+ id + "的StockDetail实体不存在！");
        }
        stockDetailService.updateById(stockDetail);
        // 添加报废流程
        ScrapDetail scrapDetail = new ScrapDetail();
        scrapDetail.setStockDetailId(stockDetail.getId());
        scrapDetail.setAmount(amount);
        this.create(Collections.singletonList(scrapDetail), BillContentEnum.ZB.getCode(), agencyUserModel);
    }

    @Override
    public void delPerson(Long id) {
        OrgUsr usr = orgUsrMapper.selectById(id);
        if (!ObjectUtils.isEmpty(usr)) {
            usr.setIsDelete(true);
            orgUsrMapper.updateById(usr);
        }
    }

}
