package com.sifang.modules.supply.warehouse.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Record;
import com.sifang.modules.flowable.service.ProcessFlowableService;
import com.sifang.modules.flowable.utils.FormUtils;
import com.sifang.modules.htySap.service.SapProcureApplyService;
import com.sifang.modules.order.utils.excelExt.ExcelReader;
import com.sifang.modules.platform.utils.PlantformUtils;
import com.sifang.modules.sunshine.SystemSetting.utils.BusinessException;
import com.sifang.modules.sunshine.SystemSetting.utils.StringUtil;
import com.sifang.modules.supply.order.request.ApplyOrderDetailReq;
import com.sifang.modules.supply.setting.dao.CrmSupplyWarehouseDao;
import com.sifang.modules.supply.stock.dao.SupplyMaterialDao;
import com.sifang.modules.supply.stock.entity.SupplyMaterial;
import com.sifang.modules.supply.stock.handler.ExcelPurchaseImportMaterialHandler;
import com.sifang.modules.supply.stock.utils.MaterialUtils;
import com.sifang.modules.supply.warehouse.dao.CrmFittingStockUpApplyDao;
import com.sifang.modules.supply.warehouse.dao.CrmFittingStockUpApplyDetailDao;
import com.sifang.modules.supply.warehouse.entity.CrmFittingStockUpApply;
import com.sifang.modules.supply.warehouse.entity.CrmFittingStockUpApplyDetail;
import com.sifang.modules.supply.warehouse.handler.ExcelImportFittingStockHandler;
import com.sifang.modules.supply.warehouse.request.AddFittingStockReq;
import com.sifang.modules.supply.warehouse.request.MateFittingVo;
import com.sifang.modules.supply.warehouse.vo.ImportFittingStockVo;
import com.sifang.modules.supply.warehouse.vo.PurchaseImportMaterialVo;
import com.sifang.modules.sys.common.UserUtils;
import com.sifang.modules.sys.common.entity.User;
import com.sifang.modules.sys.common.service.BaseService;
import com.sifang.modules.sys.common.utils.DateUtils;
import com.sifang.modules.sys.common.utils.IdGen;
import com.sifang.modules.sys.util.CrmUtils;
import com.sifang.modules.sys.util.GuardUtils;
import com.sifang.modules.sys.util.LayuiPage;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CrmFittingStockUpApplyService extends BaseService {

    @Autowired
    private CrmFittingStockUpApplyDao stockUpApplyDao;

    @Autowired
    private CrmFittingStockUpApplyDetailDao stockUpApplyDetailDao;

    @Autowired
    private ProcessFlowableService flowableService;

    @Autowired
    TaskService taskService;

    @Autowired
    private SupplyMaterialDao supplyMaterialDao;

    @Autowired
    protected SapProcureApplyService sapProcureApplyService;

    @Autowired
    CrmSupplyWarehouseDao warehouseDao;
    public void fittingStockUpList(LayuiPage<Record> page, Map<String, String> map){
        User user = UserUtils.getUser();
        stockUpApplyDao.fittingStockUpList(page,map,user);
    }

    public CrmFittingStockUpApply getFittingApply(String id){
        return stockUpApplyDao.get(id);
    }

    public Record stockUpDetail(String id){
        return stockUpApplyDao.stockUpDetail(id);
    }

    public List<Record> getFittingApplyDetail(String id){
        List<Record> list=stockUpApplyDetailDao.getFittingApplyDetail(id);
        return list;
    }


    @Transactional(rollbackFor = Exception.class)
    public void saveFittingStockApply(AddFittingStockReq req){
        User user = UserUtils.getUser();
        CrmFittingStockUpApply stockUpApply;
        Date date=new Date();
        if(StringUtil.isBlank(req.getId())){ //新增的
            stockUpApply=new CrmFittingStockUpApply();
            stockUpApply.setId(IdGen.uuid());
            stockUpApply.setNumber("BH"+PlantformUtils.getOrderNumber());
            stockUpApply.setCreateBy(user.getId());
            stockUpApply.setCreateName(req.getCreateName());
            stockUpApply.setCreateTime(date);
            stockUpApply.setStatus("0");
            stockUpApply.setDepartmentId(user.getDepartmentId());
        }else{
            stockUpApply=stockUpApplyDao.get(req.getId());
        }
        if("2".equals(req.getActionType())){  //提交
            GuardUtils.notBlank(req.getInWarehouseId(),"备货仓库不能为空!");
           /* GuardUtils.notBlank(req.getFittingType(),"备货类型不能为空!");*/
            if(req.getDetails()==null || req.getDetails().size()<=0){
                throw new IllegalArgumentException("物料清单不能为空!");
            }
            List<String> ifHave=new ArrayList<>();
            for(ApplyOrderDetailReq detail:req.getDetails()){
                GuardUtils.notBlank(detail.getMaterialTypeId(),"物料类型不能为空!");
                GuardUtils.notBlank(detail.getMaterialSpecs(),"物料规格不能为空!");
                GuardUtils.notNull(detail.getAmount(),"申请数量不能为空!");
                if(ifHave.contains(detail.getMaterialTypeId()+'_'+detail.getMaterialSpecs())){
                    throw new IllegalArgumentException("物料类型："+detail.getMaterialType()+"  物料规格："+detail.getMaterialSpecs()+" 的物料重复申请！");
                }
                ifHave.add(detail.getMaterialTypeId()+'_'+detail.getMaterialSpecs());
            }


            stockUpApply.setStatus("1");
        }
        BigDecimal totalApplyAmount=BigDecimal.ZERO;
        stockUpApply.setInWarehouseId(req.getInWarehouseId());
        stockUpApply.setFittingType(req.getFittingType());
        stockUpApply.setRemarks(req.getRemarks());
        List<CrmFittingStockUpApplyDetail> details=new ArrayList<>();
        if(req.getDetails()!=null || req.getDetails().size()>0){
            for(ApplyOrderDetailReq detailReq:req.getDetails()){
                CrmFittingStockUpApplyDetail applyDetail=new CrmFittingStockUpApplyDetail();
                applyDetail.setMainId(stockUpApply.getId());
                applyDetail.setMaterialType(detailReq.getMaterialType());
                applyDetail.setMaterialTypeId(detailReq.getMaterialTypeId());
                applyDetail.setRemark(detailReq.getRemark());
                applyDetail.setAmount(detailReq.getAmount());
                applyDetail.setMaterialSpec(detailReq.getMaterialSpecs());
                totalApplyAmount=totalApplyAmount.add(detailReq.getAmount());
                applyDetail.setStatus("1");
                details.add(applyDetail);
            }
        }
        stockUpApply.setTotalApplyAmount(totalApplyAmount);

        if(StringUtil.isBlank(stockUpApply.getProcessInstanceId()) && "2".equals(req.getActionType())){ //提交
            Record rd = FormUtils.getdefLatest(FormUtils.STOCK_UP_APPLY);
            if(rd == null){
                throw  new IllegalArgumentException("流程未定义，不可发布申请");
            }
            String processName="备货申请-"+user.getUserName()+'-'+ DateUtils.formatDate(date,"yyyy-MM-dd HH:mm:ss");
            String processInstanceId=flowableService.startProcessFlowable(user,stockUpApply.getId(),rd,FormUtils.STOCK_UP_APPLY,date,user.getUserName(),"",processName,"");
            stockUpApply.setProcessInstanceId(processInstanceId);
            stockUpApply.setProcessDefId(rd.getStr("id"));

            stockUpApply.setOperateUserIds(user.getId()+","+rd.getStr("oneAuditUseId"));
            String taskName=FormUtils.getOneStepTaskName(rd.getStr("id"));
            stockUpApply.setTaskName(taskName);

            stockUpApply.setSubmitTime(date);
            logger.info(">>>>>>>>>>>>>>>saveCashOutApply>>>>>>>>taskId:{},taskName:{}",stockUpApply.getProcessInstanceId(),stockUpApply.getTaskName());
        }else if(StringUtil.isNotBlank(stockUpApply.getProcessInstanceId()) && "2".equals(req.getActionType())){ //编辑后的提交
            Task task = taskService.createTaskQuery().processInstanceId(stockUpApply.getProcessInstanceId()).taskAssignee(user.getId()).singleResult();
            flowableService.approveTask2(task,"编辑后提交",stockUpApply.getId(),user, FormUtils.STOCK_UP_APPLY);

        }
        //删除历史的明细记录
        stockUpApplyDetailDao.deleteDetail(stockUpApply.getId());
        stockUpApplyDao.save(stockUpApply);
        if(details.size()>0){
            stockUpApplyDetailDao.save(details);
        }
    }

    //审核通过
    @Transactional(rollbackFor = Exception.class)
    public void examineFittingStockUpApplyApprove(String id,String taskId,String content){
        logger.info(">>>>>>>>>>>>>examineFittingStockUpApplyApprove  id:{},task:{}",id,taskId);
        User user = UserUtils.getUser();
        CrmFittingStockUpApply apply=stockUpApplyDao.get(id);
        logger.info(">>>>>>>>>>>>>>>>examineFittingStockUpApplyApprove   taskName:{}>",apply.getTaskName());
        apply.setExamineOpinion(content);
        stockUpApplyDao.save(apply);
        Date date=new Date();
        //审批通过
       /* flowableService.approveTask(taskId,content,apply.getId(),user,date,FormUtils.STOCK_UP_APPLY,apply.getProcessDefId());
        Task vacationApply = taskService.createTaskQuery().processInstanceId(apply.getProcessInstanceId()).singleResult();

        if(vacationApply!=null){
            apply.setTaskName(vacationApply.getName());
            apply.setTaskId(vacationApply.getId());
        }
        apply.setOperateUserIds(apply.getOperateUserIds()+","+user.getId());*/
        Task task = taskService.createTaskQuery().processInstanceId(apply.getProcessInstanceId()).taskAssignee(user.getId()).singleResult();
        flowableService.approveTask2(task,content,apply.getId(),user, FormUtils.STOCK_UP_APPLY);
    }

    //审批驳回
    @Transactional(rollbackFor = Exception.class)
    public void rejectFittingStockUpApplyTask(String id,String taskId,String content){
        logger.info(">>>>>>>>>>>>>rejectFittingStockUpApplyTask  id:{},task:{}",id,taskId);
        User user = UserUtils.getUser();
        CrmFittingStockUpApply apply=stockUpApplyDao.get(id);
        apply.setContent(content);
        apply.setExamineOpinion(content);
        stockUpApplyDao.save(apply);
        Task task = taskService.createTaskQuery().processInstanceId(apply.getProcessInstanceId()).taskAssignee(user.getId()).singleResult();
        flowableService.rejectTask2(task,content,id,user,FormUtils.STOCK_UP_APPLY,apply.getCreateBy());
    }

    @Transactional(rollbackFor = Exception.class)
    public void tempFittingStockMateFitting(MateFittingVo mateFittingVo){
        logger.info(">>>>>>>>>>>>>tempFittingStockMateFitting  mateFittingVo:{} ",mateFittingVo.toString());
        User user=UserUtils.getUser();
        Date date=new Date();
        CrmFittingStockUpApply stockUpApply=stockUpApplyDao.get(mateFittingVo.getId());
        stockUpApply.setMateBy(user.getId());
        stockUpApply.setMateTime(date);
        if("2".equals(mateFittingVo.getActionType())){  //提交
           //判断是否全部匹配了
            int i=1;
            for(ApplyOrderDetailReq req: mateFittingVo.getDetails()){
                  if(StringUtil.isBlank(req.getTargetId())){
                      throw new IllegalArgumentException("第"+i+"行物料，没有匹配");
                  }
            }
            stockUpApply.setStatus("4");
        }

        List<CrmFittingStockUpApplyDetail>  details=new ArrayList<>();
        int hh=1;
        for(ApplyOrderDetailReq req: mateFittingVo.getDetails()){
            SupplyMaterial material = supplyMaterialDao.get(req.getTargetId());
            CrmFittingStockUpApplyDetail applyDetail=new CrmFittingStockUpApplyDetail();
            applyDetail.setMainId(stockUpApply.getId());
            applyDetail.setMaterialId(req.getTargetId());
            applyDetail.setMaterialCode(req.getMaterialCode());
            applyDetail.setMaterialType(req.getMaterialType());
            applyDetail.setMaterialTypeId(req.getMaterialTypeId());
            applyDetail.setMaterialSpec(req.getMaterialSpecs());
            applyDetail.setRemark(req.getRemark());
            applyDetail.setAmount(req.getAmount());
            applyDetail.setStatus("1");
            details.add(applyDetail);
            hh++;
        }
        //删除历史的明细记录
        stockUpApplyDetailDao.deleteDetail(stockUpApply.getId());
        stockUpApplyDao.save(stockUpApply);
        stockUpApplyDetailDao.save(details);
    }

    //校验导入的备货申请
    public Map<String,Object> checkImportFittingStockApply(Map<String, String> params, InputStream in){
        logger.info(">>>>>>>>>>>>>checkImportFittingStockApply");
        Map<String, Object> retMap = Maps.newHashMap();
        retMap.put("operType", "check");
        ExcelImportFittingStockHandler handler = new ExcelImportFittingStockHandler();
        handler.setStartSheet(1);
        handler.setStartRow(2);
        try {
            new ExcelReader().check(in, params.get("extName"), handler);
            Map<String, Object> map = (Map<String, Object>) handler.getHandlerResult();
            String templateError = (String) map.get("TemplateError");
            if(!handler.isCheckFlag()){
                handler.appendErrorDetail("<p>未填充数据</p>");
            }
            //获取所有物料类型
            List<String> types = MaterialUtils.findMaterialTypeName();

            List<String> warehouseName=MaterialUtils.getPlateWarehouseName();

            List<ImportFittingStockVo> stockVos = handler.getStockVos();
            int i=1;
            List<String> ifHave=new ArrayList<>();
            for(ImportFittingStockVo vo:stockVos){
                if (!types.contains(vo.getMaterialType())) {
                    handler.appendErrorDetail("第" + (i + 1) + "行物料类型不存在");
                }
                if(StringUtil.isNotBlank(vo.getInWarehouseName()) && !warehouseName.contains(vo.getInWarehouseName())){
                    handler.appendErrorDetail(vo.getInWarehouseName() + "，该仓库不存在!");
                }

                if(ifHave.contains(vo.getMaterialType()+'_'+vo.getMaterialSpec())){
                    handler.appendErrorDetail("物料类型："+vo.getMaterialType()+" ，物料规格："+vo.getMaterialSpec()+" 的物料重复申请！");
                }
                ifHave.add(vo.getMaterialType()+'_'+vo.getMaterialSpec());
            }
            String hanl = handler.getErrorDetail();
            if (StrKit.notBlank(templateError)){
                retMap.put("errorDetail", templateError);
                retMap.put("errorMessage", "y");
            }else if (StringUtils.isNotBlank(hanl)) {
                retMap.put("errorDetail", hanl);
                retMap.put("errorMessage", "y");
            } else if ("overLimit".equalsIgnoreCase((String) map.get("overLimit"))) {
                retMap.put("overLimit", "y");
            } else {
                retMap.put("pass", "y");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return retMap;
    }

    //导入备货申请
    public Map<String,Object> importImportFittingStockApply(Map<String, String> params, InputStream in){
        logger.info(">>>>>>>>>>>>>importImportFittingStockApply");
        Map<String, Object> retMap = Maps.newHashMap();
        retMap.put("operType", "import");
        ExcelImportFittingStockHandler handler = new ExcelImportFittingStockHandler();
        handler.setStartSheet(1);
        handler.setStartRow(3);
        try {
            new ExcelReader().readExcel(in, params.get("fileName"), handler);
            //获取所有物料类型
            List<Record> types = MaterialUtils.findMaterialType();
            Map<String, Record> typeMap = types.stream()
                    .collect(Collectors.toMap(e -> e.getStr("name"), e -> e, (a, b) -> a));

            //获取平台的仓库
            List<Record> warehouses=MaterialUtils.getPlateWarehouse();
            Map<String,String> warehouseMap=warehouses.stream()
                    .collect(Collectors.toMap(e -> e.getStr("name"), e -> e.getStr("id"), (a, b) -> a));

            List<ImportFittingStockVo> stockVos = handler.getStockVos();
            CrmFittingStockUpApply stockUpApply=new CrmFittingStockUpApply();
            stockUpApply.setId(IdGen.uuid());
            stockUpApply.setNumber("BH"+PlantformUtils.getOrderNumber());
            stockUpApply.setStatus("3");  //待匹配
            BigDecimal totalApplyAmount=BigDecimal.ZERO;
            List<CrmFittingStockUpApplyDetail> details=new ArrayList<>();
            for (ImportFittingStockVo materialVo : stockVos) {
                if(StringUtil.isNotBlank(materialVo.getInWarehouseName())){
                    String warehouseId=warehouseMap.get(materialVo.getInWarehouseName());
                    if(StringUtil.isBlank(warehouseId)){
                        throw new BusinessException(materialVo.getInWarehouseName()+"，此仓库不存在!");
                    }
                    stockUpApply.setInWarehouseId(warehouseId);
                    stockUpApply.setCreateName(materialVo.getCreateName());
                    stockUpApply.setCreateTime(materialVo.getCreateTime());
                    stockUpApply.setSubmitTime(materialVo.getCreateTime());
                }
                CrmFittingStockUpApplyDetail applyDetail=new CrmFittingStockUpApplyDetail();
                applyDetail.setMainId(stockUpApply.getId());
                applyDetail.setMaterialType(materialVo.getMaterialType());
                Record typeRecord=typeMap.get(materialVo.getMaterialType());
                if(typeRecord==null){
                    throw new BusinessException(materialVo.getMaterialType()+"，此物料类型不存在!");
                }
                applyDetail.setMaterialTypeId(typeRecord.getStr("id"));
                applyDetail.setAmount(new BigDecimal(materialVo.getAmount()));
                applyDetail.setMaterialSpec(materialVo.getMaterialSpec());
                totalApplyAmount=totalApplyAmount.add(applyDetail.getAmount());
                applyDetail.setStatus("1");
                details.add(applyDetail);
            }
            stockUpApply.setTotalApplyAmount(totalApplyAmount);
            stockUpApplyDao.save(stockUpApply);
            if(details.size()>0){
                stockUpApplyDetailDao.save(details);
            }
            retMap.put("pass", "y");
        } catch (BusinessException b) {
            throw new BusinessException(b.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            logger.info(">>>>>>>>>>>>importImportFittingStockApply e:{}",e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return retMap;
    }
}
