package com.bonus.material.ma.service.impl;


import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.ma.domain.*;
import com.bonus.material.ma.domain.vo.ExceptionEnum;
import com.bonus.material.ma.domain.vo.GlobalContants;
import com.bonus.material.ma.mapper.WarehousingMapper;
import com.bonus.material.ma.service.ITypeService;
import com.bonus.material.ma.service.WarehousingService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

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

/**
 * @author hay
 * @description 入库盘点
 * @date 2024/3/27 13:32
 */
@Service
@Slf4j
public class WarehousingServiceImpl implements WarehousingService {

    @Autowired
    private WarehousingMapper warehousingMapper;

    @Resource
    private ITypeService typeService;

//    @Autowired
//    private PurchaseInputMapper purchaseInputMapper;

    /**
     * 查询入库盘点列表
     * @param bean
     * @return
     */
    @Override
    public List<PutInStorageBean> getList(PutInStorageBean bean) {
        return warehousingMapper.getList(bean);
    }

    @Override
    public List<SupplierInfo> selectMaSupplierInfoList(SupplierInfo maSupplierInfo)
    {
        return warehousingMapper.selectMaSupplierInfoList(maSupplierInfo);
    }

    /**
     * 生成code编码
     * @return
     */
    public String genderBackCode() {
        log.info("enter method genderBackCode");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        Date nowDate = DateUtils.getNowDate();
        String format = dateFormat.format(nowDate);
        int taskNum = warehousingMapper.selectTaskNumByMonth(nowDate) + 1;
        String code = "";
        if (taskNum > GlobalContants.NUM1 && taskNum < GlobalContants.NUM2) {
            code = "PD" + format + "-00" + taskNum;
        } else if (taskNum > GlobalContants.NUM3 && taskNum < GlobalContants.NUM4) {
            code = "PD" + format + "-0" + taskNum;
        } else {
            code = "PD" + format + "-000" + taskNum;
        }
        log.info("end method genderBackCode" + code);
        return code;
    }

    /**
     * 新增入库盘点
     * @param dto
     * @return
     */
    @Override
//    @Transactional(rollbackFor = Exception.class)
    public AjaxResult savePutInfo(SavePutInfoDto dto) {
        log.info("新增入库盘点入参dto：{}", dto);
        Long userId = SecurityUtils.getLoginUser().getUserid();
        dto.setCreator(userId);
        String code = genderBackCode();
        List<MachIneDto> machIneDtoList = dto.getMachIneDtoList();
        //判断提交表单中是否存在相同编码
        for (int i = 0; i < machIneDtoList.size() - 1; i++) {
            for (int j = i + 1; j < machIneDtoList.size(); j++) {
                if (StringUtils.isNotEmpty(machIneDtoList.get(i).getMaCode()) && StringUtils.isNotEmpty(machIneDtoList.get(j).getMaCode())
                        && machIneDtoList.get(i).getMaCode().equals(machIneDtoList.get(j).getMaCode())) {
                    throw new ServiceException("列表中包含以下相同的设备编码，请修改后重新提交：" + machIneDtoList.get(i).getMaCode());
                }
            }
        }
        //判断提交中设备编码是否与库中相同
        if (CollectionUtils.isNotEmpty(machIneDtoList)) {
            for (MachIneDto machIneDto : machIneDtoList) {
                if (StringUtils.isNotBlank(machIneDto.getMaCode())) {
                    int count = selectByMaCode(machIneDto.getMaCode());
                    if (count != 0) {
                        throw new ServiceException("以下设备编码与库中数据存在重复，请修改后重新提交：" + machIneDto.getMaCode());
                    }
                }
            }
        }
        int res;
        try {
            //1. 判断是数量还是编号入库，保存到不同表
            //1.1 如果是编号入库
            if (dto.getIsCode()) {
                res = insertMaMachineInfo(dto, code);
                if (res == 0) {
                    log.error("insertMaMachineInfo方法插入异常");
                    throw new RuntimeException("insertMaMachineInfo方法插入异常");
                }
            } else {
                //2.插入ma_type_put_in_storage_info表和ma_type_put_in_storage_details表
                res = insertPutInfo(dto, code);
                if (res == 0) {
                    log.error("insertPutInfo方法插入异常");
                    throw new RuntimeException("insertPutInfo方法插入异常");
                }
            }

        } catch (Exception e) {
            log.error("保存入库盘点异常:{}",e.getMessage());
//            // 添加事务回滚逻辑，保证入库全部成功或者全部失败
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(ExceptionEnum.SAVE_TO_DATABASE.getCode(), ExceptionEnum.SAVE_TO_DATABASE.getMsg());
        }
        return AjaxResult.success(res);
    }

    /**
     * 根据设备编码code查重
     * @param maCode
     * @return
     */
    private int selectByMaCode(String maCode) {
        return warehousingMapper.selectByMaCode(maCode);
    }

    /**
     * 编号新增，插入ma_machine、ma_machine_label和ma_label_bind
     * @param dto
     * @param code
     * @return
     */
    private int insertMaMachineInfo(SavePutInfoDto dto,  String code) {
        int res = 0;
        if (dto.getNum() != null) {
            MachIneDto machIneDto = dto.getMachIneDtoList().get(0);
            machIneDto.setCode(code);
            machIneDto.setPutInType(dto.getPutInType());
            machIneDto.setCreator(dto.getCreator());
            machIneDto.setNum(dto.getNum());
            machIneDto.setIsCode(dto.getIsCode());
            machIneDto.setTypeId(dto.getTypeId());
            machIneDto.setRemarks(dto.getRemarks());
            res += insertInfo(machIneDto);
            machIneDto.setInfoId(machIneDto.getId());
        }
        for (int i = 0; i < dto.getMachIneDtoList().size(); i++) {
            MachIneDto machIneDto = dto.getMachIneDtoList().get(i);
            machIneDto.setCode(code);
            machIneDto.setIsCode(dto.getIsCode());
            machIneDto.setTypeId(dto.getTypeId());
            machIneDto.setCreator(dto.getCreator());
            machIneDto.setPutInType(dto.getPutInType());
            machIneDto.setNum(dto.getNum());
            machIneDto.setCheckMan(dto.getCheckMan());
            machIneDto.setInfoId(dto.getMachIneDtoList().get(0).getInfoId());
            res += insertMachineInfo(machIneDto);
            //根据类型追加ma_type表里面的num
            Type type = new Type();
            type.setModelTitle("盘点入库");
            type.setCode(code);
            type.setStyle("3");
            type.setTypeId(Long.parseLong(machIneDto.getTypeId()));
            type.setInputNum(BigDecimal.ONE);
            type.setMaId(machIneDto.getMaId());
            res += typeService.updateNumAddOrSubtract(type);
        }
        return res;
    }

    /**
     * 插入ma_type_put_in_storage_info表,返回主键id
     * @param machIneDto
     * @return
     */
    private int insertInfo(MachIneDto machIneDto) {
        return warehousingMapper.saveInfo(machIneDto);
    }

    /**
     * 方法抽取，保持到ma_machine、ma_machine_label和ma_label_bind
     * @param machIneDto
     * @return
     */
    private int insertMachineInfo(MachIneDto machIneDto) {
        int res = warehousingMapper.insertMachine(machIneDto);

        res += insertTypePutInStorageInfo(machIneDto);
        return res;
    }

    /**
     * 方法抽取
     * @param machIneDto
     * @return
     */
    private int insertTypePutInStorageInfo(MachIneDto machIneDto) {
        //ma_type_put_in_storage_details表
        return warehousingMapper.saveDetails(machIneDto);
    }

    /**
     * 插入表方法
     * @param dto
     * @return
     */
    private int insertPutInfo(SavePutInfoDto dto, String code) {
        int res = 0;
        Integer total = dto.getMachIneDtoList().stream()
                .map(MachIneDto::getPutInStoreNum)
                .filter(num -> num != null)
                .collect(Collectors.summingInt(Integer::intValue));
        if (CollectionUtils.isNotEmpty(dto.getMachIneDtoList())) {
            MachIneDto machIneDto = dto.getMachIneDtoList().get(0);
            machIneDto.setCode(code);
            machIneDto.setPutInType(dto.getPutInType());
            machIneDto.setCreator(dto.getCreator());
            machIneDto.setIsCode(dto.getIsCode());
            machIneDto.setTotalNum(total);
            machIneDto.setRemarks(dto.getRemarks());
            res += insertInfo(machIneDto);
            machIneDto.setInfoId(machIneDto.getId());
        }
        for (int i = 0; i < dto.getMachIneDtoList().size(); i++) {
            MachIneDto machIneDto = dto.getMachIneDtoList().get(i);
            machIneDto.setCreator(dto.getCreator());
            machIneDto.setPutInType(dto.getPutInType());
            machIneDto.setRemarks(dto.getRemarks());
            machIneDto.setCode(code);
            machIneDto.setInfoId(dto.getMachIneDtoList().get(0).getInfoId());
            res += insertTypePutInStorageInfo(machIneDto);
            //根据类型追加ma_type表里面的num
            Type type = new Type();
            type.setModelTitle("盘点入库");
            type.setCode(code);
            type.setStyle("3");
            type.setTypeId(Long.parseLong(machIneDto.getTypeId()));
            type.setInputNum(BigDecimal.valueOf(machIneDto.getPutInStoreNum()));
            res += typeService.updateNumAddOrSubtract(type);
            //res += updateMaTypeInfo(machIneDto.getTypeId(), machIneDto.getPutInStoreNum());
        }
        return res;
    }


    /**
     * 根据入库单号查看详情
     * @param bean
     * @return
     */
    @Override
    public List<PutInStorageBean> getDetails(PutInStorageBean bean) {
        return warehousingMapper.getDetails(bean);
    }
}
