package com.sy.coinage.workshop.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.sy.coinage.core.constants.BusinessEnum;
import com.sy.coinage.core.exception.RetException;
import com.sy.coinage.core.vo.CacheUserVO;
import com.sy.coinage.sys.model.Dept;
import com.sy.coinage.sys.model.Dict;
import com.sy.coinage.sys.model.User;
import com.sy.coinage.sys.service.IDeptService;
import com.sy.coinage.sys.service.IDictService;
import com.sy.coinage.sys.service.IUserService;
import com.sy.coinage.websocket.WebSocketServer;
import com.sy.coinage.workshop.WareUtil;
import com.sy.coinage.workshop.req.WorkshopOutboundReq;
import com.sy.coinage.workshop.req.WorkshopTransferReq;
import com.sy.coinage.workshop.req.vo.SerialNumberVO;
import com.sy.coinage.workshop.service.*;
import com.sy.coinage.workshop.vo.OutboundVO;
import com.sy.coinage.workshop.vo.ViewInfoVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sy.coinage.workshop.dao.WorkshopTransferDao;
import com.sy.coinage.workshop.model.*;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.Date;
import java.util.List;

/**
 * -车间内部迁移表ServiceImpl
 */
@Service
public class WorkshopTransferServiceImpl extends ServiceImpl<WorkshopTransferDao, WorkshopTransfer>
        implements IWorkshopTransferService {
    @Autowired
    private IBaseInfoService baseInfoService;

    @Autowired
    private IStockService stockService;

    @Autowired
    private IWorkshopTransferDetailService workshopTransferDetailService;

    @Autowired
    private IWorkshopAccountService workshopAccountService;

    @Autowired
    private IProductService productService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IDeptService deptService;

    @Autowired
    private IDictService dictService;

    @Autowired
    private IWorkshopLogService workshopLogService;

    @Autowired
    private ILogisticsService logisticsService;

    @Override
    @Transactional
    public void add(WorkshopTransferReq req) {
        Dept dept = this.deptService.getByCode(req.getWareId());
        Product product = productService.getById(req.getSecuritiesId());
        WorkshopTransfer model = new WorkshopTransfer();
//        model.setOperatorId(user.getId());
//        model.setOperatorCn(user.getRealName());
        // 操作类型1:产成品到剔除品库位 2: 剔除品库位到机台
        model.setOpType(1);
        model.setSecuritiesId(req.getSecuritiesId());
        model.setSecurities(product.getSecurities());
        model.setLocFrom(1);
        model.setLocTo(2);
        model.setRacketNum(req.getDetailList().size());
        model.setDeptId(dept.getId());
        model.setDept(dept.getName());
        this.save(model);
        // 添加明细
        Integer totalBox = this.addDetailList(model, req.getDetailList(), product, req.getWareId());
        Integer piecesTotal = totalBox * product.getAmountPerBox();
        // 更新实时产成品库存
        this.stockService.stockSub(model.getSecuritiesId(), product.getSecurities(),
                1, req.getWareId(), null, req.getDetailList().size(), 0, 0, 0);
        // 更新实时剔除品库存
        this.stockService.stockAdd(model.getSecuritiesId(), product.getSecurities(),
                2, req.getWareId(), null, req.getDetailList().size(), 0, 0, 0);
        // 添加车间台账 产成品库内部流转到剔除品库
//        Integer wareTotal = WareUtil.piecesTotal(stock1, product);
        Integer wareTotal = this.stockService.getProductStockTotal(req.getWareId(), model.getSecuritiesId(), product);
        // 2-封箱成品付出(收入负)
        this.workshopAccountService.shopOut(2, model.getDeptId(), model.getDept(), null,
                null, model.getCheckId(), model.getChecker(), null, piecesTotal,
                wareTotal, 2, 1, "剔除品", null, model.getSecuritiesId(), model.getSecurities());
        Integer eliminateStockTotal = this.stockService.getEliminateStockTotal(req.getWareId(), req.getSecuritiesId(), product);
        // 3-剔除品收入(付出负)
        this.workshopAccountService.shopIn(2, model.getDeptId(), model.getDept(), null,
                null, model.getCheckId(), model.getChecker(), null, piecesTotal,
                eliminateStockTotal, 3, 1, "封箱成品", null, model.getSecuritiesId(), model.getSecurities());
    }

    @Override
    @Transactional
    public void eliminateOut(WorkshopOutboundReq req, CacheUserVO user) {
        Dept dept = this.deptService.getByCode(req.getWareId());
        // 如果没有品名 查部门最后一条
        if (req.getSecuritiesId() == null || req.getSecuritiesId() == 0) {
            BaseInfo info = baseInfoService.getLast(dept.getId());
            req.setSecuritiesId(info.getSecuritiesId());
        }
        Date now = new Date();
        Product product = productService.getById(req.getSecuritiesId());
        User checkUser = this.userService.getById(req.getCheckId());
        WorkshopTransfer model = new WorkshopTransfer();
//        model.setOperatorId(user.getId());
//        model.setOperatorCn(user.getRealName());
        // 操作类型1:产成品到剔除品库位 2: 剔除品库位到机台
        model.setOpType(2);
        model.setSecuritiesId(req.getSecuritiesId());
        model.setSecurities(product.getSecurities());
        model.setLocFrom(2);
        model.setLocTo(3);
        model.setDeptId(dept.getId());
        model.setDept(dept.getName());
        model.setBoxNum(req.getBoxNum());
        model.setPiecesTotal(req.getPiecesTotal());
        model.setCheckId(req.getCheckId());
        model.setChecker(checkUser.getRealName());
        model.setOperatorId(user.getId());
        model.setOperatorCn(user.getRealName());
        Integer racketNum = 0;
        // 录入自动拍数
        if (req.getAutoLs() != null && req.getAutoLs().size() > 0) {
            racketNum = racketNum + req.getAutoLs().size();
        }
        // 录入手动拍数
        if (req.getManualLs() != null && req.getManualLs().size() > 0) {
            racketNum = racketNum + req.getManualLs().size();
        }
        model.setRacketNum(racketNum);
        this.save(model);
        String checkUserName = this.userService.getById(req.getCheckId()).getRealName();
        Dict dict = dictService.getByVal("shopWareOpt", req.getWareId(), null);
        Integer wareId = Integer.parseInt(dict.getVal());
        OutboundVO outboundVO = new OutboundVO();
        // 录入自动拍数
        if (req.getAutoLs() != null && req.getAutoLs().size() > 0) {
            for (SerialNumberVO vo : req.getAutoLs()) {
                // 验证库位状态
                BaseInfo b = this.baseInfoService.getByRfid(vo.getRfid());
                if (b.getLocAreaId() == null || b.getLocAreaId().intValue() != 2) {
                    throw new RetException("库位状态异常，不能出库，请先内部移库");
                }
                BaseInfo info = this.addDetail(model, vo.getSerialNumber(), vo.getRfid(), product, req.getWareId(), now);
                if ((info.getUnpackageStatus() != null && info.getUnpackageStatus().intValue() == 2) ||
                        info.getOriginType() == 2) {
                    outboundVO.setBoxQty(outboundVO.getBoxQty() + info.getQty());
                } else {
                    outboundVO.setRacketQty(outboundVO.getRacketQty() + 1);
                }
            }
        }
        // 录入手动拍数
        if (req.getManualLs() != null && req.getManualLs().size() > 0) {
            for (SerialNumberVO vo : req.getManualLs()) {
                // 验证库位状态
                BaseInfo b = this.baseInfoService.getBySerialNumber(vo.getSerialNumber(), 2);
                if (b.getLocAreaId() == null || b.getLocAreaId().intValue() != 2) {
                    throw new RetException("库位状态异常，不能出库，请先内部移库");
                }
                BaseInfo info = this.addDetail(model, vo.getSerialNumber(), null, product, req.getWareId(), now);
                if ((info.getUnpackageStatus() != null && info.getUnpackageStatus().intValue() == 2) ||
                        info.getOriginType() == 2) {
                    outboundVO.setBoxQty(outboundVO.getBoxQty() + info.getQty());
                } else {
                    outboundVO.setRacketQty(outboundVO.getRacketQty() + 1);
                }
            }
        }
        // 零箱
        if (req.getBoxNum() != null && req.getBoxNum() > 0) {
            outboundVO.setBoxQty(outboundVO.getBoxQty() + req.getBoxNum());
            WorkshopTransferDetail detail = new WorkshopTransferDetail();
            detail.setType(2);
            detail.setTransferId(model.getId());
            detail.setQty(req.getBoxNum());
            detail.setQtyTotal(req.getBoxNum() * product.getAmountPerBox());
            this.workshopTransferDetailService.save(detail);
            this.workshopLogService.addWorkshopLog(null, null, product.getId(),
                    product.getSecurities(), null, null,
                    dept.getId(), dept.getName(),
                    user.getId(), user.getRealName(),
                    req.getCheckId(), checkUserName, 5, 3, 10, req.getBoxNum(), 0);
        }
        // 零枚
        if (req.getPiecesTotal() != null && req.getPiecesTotal() > 0) {
            WorkshopTransferDetail detail = new WorkshopTransferDetail();
            detail.setType(3);
            detail.setTransferId(model.getId());
            detail.setQty(req.getPiecesTotal());
            detail.setQtyTotal(req.getPiecesTotal());
            this.workshopTransferDetailService.save(detail);
            this.workshopLogService.addWorkshopLog(null, null, product.getId(),
                    product.getSecurities(), null, null,
                    dept.getId(), dept.getName(),
                    user.getId(), user.getRealName(),
                    req.getCheckId(), checkUserName, 5, 3, 10, 0, req.getPiecesTotal());
        }
        // 剔除品库
        Integer areaId = BusinessEnum.ELIMINATE_AREA.value();
        // 更新实时剔除品库存 返回实时库存
        this.stockService.stockSub(req.getSecuritiesId(), product.getSecurities(), areaId, wareId, dict.getName(),
                racketNum, req.getBoxNum(), req.getPiecesTotal(), 0);
        // 添加车间台账 剔除品库内部出库到机台
        Integer piecesTotal = outboundVO.getRacketQty() * product.getBoxAmount() * product.getAmountPerBox() + outboundVO.getBoxQty() * product.getAmountPerBox() + (req.getPiecesTotal() == null ? 0 : req.getPiecesTotal());
        Integer eliminateStockTotal = this.stockService.getEliminateStockTotal(wareId, req.getSecuritiesId(), product);
        // 3剔除品实物收发卡
        this.workshopAccountService.shopOut(1, dept.getId(), dept.getName(), user.getId(),
                user.getRealName(), req.getCheckId(), checkUserName, null, piecesTotal,
                eliminateStockTotal, 3, 1, "机台", null, req.getSecuritiesId(),
                product.getSecurities());
    }

    private BaseInfo addDetail(WorkshopTransfer model, String serialNumber, String rfid, Product product, Integer wareId, Date now) {
        BaseInfo info = this.baseInfoService.updateWorkShopStatus(serialNumber, rfid, 2, 13, null, null, null, null);
        WorkshopTransferDetail detail = new WorkshopTransferDetail();
        detail.setType(1);
        detail.setRfid(info.getRfid());
        detail.setTransferId(model.getId());
        detail.setSerialNumber(info.getSerialNumber());
        detail.setQty(1);
        detail.setQtyTotal(info.getQty() * product.getAmountPerBox());
        detail.setCrownBetweenStr(info.getCrownBetweenStr());
        this.workshopTransferDetailService.save(detail);
        // 生命周期状态:1初始登记 2:车间入库 3:车间出库 4:总库入库 5:主库抽检出库 6.车间抽检入库确认
        // 7.车间抽检出库8 主库抽检返回确认 9返检总库出库 10:返检车间确认 11拆包12：已发货
        // FIXME 记录物流信息日志表
        this.logisticsService.add(info.getRfid(), serialNumber, wareId, null, 3, model.getCheckId(), model.getChecker(), model.getOperatorId(), model.getOperatorCn(), null, null);
        this.sendOutMsg1(detail, model.getChecker(), model.getOperatorCn(), info, wareId, now);
        this.workshopLogService.addWorkshopLog(info, info.getCrownBetweenStr(), info.getSecuritiesId(),
                info.getSecurities(), info.getRfid(), serialNumber,
                info.getDeptId(), info.getDept(),
                model.getOperatorId(), model.getOperatorCn(),
                model.getCheckId(), model.getChecker(), 5, 3, 10, null, null);
        return info;
    }

    private Integer addDetailList(WorkshopTransfer vo, List<Integer> detailList, Product product, Integer wareId) {
        Integer totalBox = 0;
        for (Integer id : detailList) {
            BaseInfo info = this.baseInfoService.getById(id);
            totalBox = totalBox + info.getQty();
            // 成品库到剔除品库
            info.setLocAreaId(2);
            this.baseInfoService.updateById(info);
            WorkshopTransferDetail detail = new WorkshopTransferDetail();
            detail.setType(1);
            detail.setRfid(info.getRfid());
            detail.setTransferId(vo.getId());
            detail.setSerialNumber(info.getSerialNumber());
            detail.setQty(1);
            detail.setQtyTotal(info.getQty() * product.getAmountPerBox());
            detail.setCrownBetweenStr(info.getCrownBetweenStr());
//            model.setCrownBetweenStr(info.getCrownPrefix() + info.getCrownFrom() + "至" + info.getCrownPrefix() + info.getCrownTo());
            this.workshopTransferDetailService.save(detail);
//            // FIXME 记录物流信息日志表
//            this.logisticsService.add(model.getRfid(), model.getSerialNumber(),
//                    wareId, null, 3, null, null,
//                    null, null, null, null);
            // 车间日志表
            // 来源地1:主库一2:主库二 3:机台 4:临时库产品库区域 5 临时库剔除品区域
            // 目的地 1:主库一2:主库二 3:机台 4:临时库产品库区域 5 临时库剔除品区域
//            this.workshopLogService.addWorkshopLog(info, model.getCrownBetweenStr(),
//                    vo.getSecuritiesId(), vo.getSecurities(), model.getRfid(), model.getSerialNumber(), vo.getDeptId(), vo.getDept(), vo.getOperatorId(),
//                    vo.getOperatorCn(),
//                    null, null, 4, 5, 9, null, null);
        }
        return totalBox;
    }

//    private Integer totalQty(Stock stock, Product product) {
//        return (stock.getRacketNum() == null ? 0 : stock.getRacketNum()) * product.getBoxAmount() * product.getAmountPerBox() + (stock.getBoxNum() == null ? 0 : stock.getBoxNum()) * product.getAmountPerBox() + (stock.getPiecesTotal() == null ? 0 : stock.getPiecesTotal());
//    }

    private void sendOutMsg1(WorkshopTransferDetail detail, String checker, String createBy, BaseInfo info, Integer wareId, Date now) {
        ViewInfoVO vo = new ViewInfoVO();
        //  (value = "总库-1复核异常 1解缴待入库 2解缴中 3解缴已入库 5已发货：
        vo.setInOrOut(3);
        vo.setCrownBetweenStr(info.getCrownBetweenStr());
        vo.setGrossWeight(info.getGrossWeight());
        vo.setTareWeight(info.getTareWeight());
        vo.setWeightor(info.getWeightor());
        vo.setPrintTime(info.getNewPrintTime());
        vo.setOperateTime(now);
        vo.setSecuritiesId(info.getSecuritiesId());
        vo.setSecurities(info.getSecurities());
        vo.setSerialNumber(info.getSerialNumber());
        vo.setRfid(info.getRfid());
        vo.setChecker(checker);
        vo.setCreateBy(createBy);
        vo.setDept(info.getDept());
        // ：临时库-1复核异常 1入库 2解缴出库 3解缴已入库 4返检待入库 5返检已入库 6内部出库
        vo.setStatus(6);
        vo.setLocWare(info.getLocWare());
        WebSocketServer.sendMessageClient(String.valueOf(wareId), vo);
    }

}
