package com.ruoyi.warehouseBusiness.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ruoyi.approvalFlow.domain.AuditItems;
import com.ruoyi.approvalFlow.service.impl.AuditItemsServiceImpl;
import com.ruoyi.basicData.domain.TCorps;
import com.ruoyi.basicData.domain.TFees;
import com.ruoyi.basicData.mapper.TCorpsMapper;
import com.ruoyi.basicData.mapper.TFeesMapper;
import com.ruoyi.basicData.mapper.TGoodsMapper;
import com.ruoyi.basicData.mapper.TWarehouseMapper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.TWarehouse;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.WarehouseException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.warehouseBusiness.domain.*;
import com.ruoyi.warehouseBusiness.domain.dto.WarehousebillsModifyDTO;
import com.ruoyi.warehouseBusiness.domain.enums.FeesTypeEnum;
import com.ruoyi.warehouseBusiness.domain.enums.WarehouseActIdEnum;
import com.ruoyi.warehouseBusiness.domain.enums.WarehouseTypeEnum;
import com.ruoyi.warehouseBusiness.domain.vo.WarehousebillsModifyVO;
import com.ruoyi.warehouseBusiness.mapper.*;
import com.ruoyi.warehouseBusiness.service.ITWarehousebillsModifyService;
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.transaction.interceptor.TransactionAspectSupport;

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

import static com.ruoyi.common.core.text.Convert.toLongArray;

/**
 * 仓库费用变更主表Service业务层处理
 *
 * @author ruoyi
 * @date 2021-10-27
 */
@Service
public class TWarehousebillsModifyServiceImpl implements ITWarehousebillsModifyService {

    @Autowired
    private TFeesMapper feesMapper;

    @Autowired
    private TGoodsMapper goodsMapper;

    @Autowired
    private TCorpsMapper corpsMapper;

    @Autowired
    private SysConfigMapper sysConfigMapper;

    @Autowired
    private BillnoDelMapper billnoDelMapper;

    @Autowired
    private TWarehouseMapper warehouseMapper;

    @Autowired
    private AuditItemsServiceImpl auditItemsService;

    @Autowired
    private TWarehouseBillsMapper warehousebillsmapper;

    @Autowired
    private BillnoSerialServiceImpl billnoSerialService;

    @Autowired
    private TWarehousebillsfeesMapper warehousebillsfeesMapper;

    @Autowired
    private TWarehousebillsModifyMapper tWarehousebillsModifyMapper;

    @Autowired
    private TWarehousebillsfeesModifyMapper tWarehousebillsfeesModifyMapper;


    /**
     * 查询仓库主(出入库)
     *
     * @param fId 仓库主(出入库)ID
     * @return 仓库主(出入库)
     */
    @Override
    public WarehousebillsModifyVO selectTWarehousebillsModifyById(Long fId) {
        TWarehousebillsModify warehousebillsModify = tWarehousebillsModifyMapper.selectTWarehousebillsModifyById(fId);
        if (Objects.isNull(warehousebillsModify)) {
            throw new WarehouseException("找不到信息");
        }
        WarehousebillsModifyVO warehousebillsModifyVO = new WarehousebillsModifyVO();
        // 根据主表id查出明细信息
        List<TWarehousebillsfeesModify> feesModifies = tWarehousebillsfeesModifyMapper.selectListByPid(fId);
        if (CollectionUtils.isNotEmpty(feesModifies)) {
            // 查出所有费用信息
            warehousebillsModifyVO.setFeesList(feesMapper.selectTFeesList(new TFees()));
            // 查出所有客户信息
            warehousebillsModifyVO.setCorpsList(corpsMapper.selectTCorpsList(new TCorps()));
            warehousebillsModifyVO.setWarehousebillsfeesModifyList(feesModifies);
        }
        // 转VO
        BeanUtils.copyProperties(warehousebillsModify, warehousebillsModifyVO);
        // 转化客户、商品、仓库名称
        TCorps tCorps = corpsMapper.selectTCorpsById(warehousebillsModifyVO.getfCorpid());
        if (Objects.nonNull(tCorps)) {
            warehousebillsModifyVO.setCorpName(tCorps.getfName());
        }
        TWarehouse tWarehouse = warehouseMapper.selectTWarehouseById(warehousebillsModify.getfWarehouseid());
        if (Objects.nonNull(tWarehouse)) {
            warehousebillsModifyVO.setWarehouseName(tWarehouse.getfName());
        }
        // 查询原仓储费用
        TWarehousebillsfees tWarehousebillsfees = new TWarehousebillsfees();
        tWarehousebillsfees.setfPid(warehousebillsModify.getfPid());
        tWarehousebillsfees.setfDc(warehousebillsModify.getfDc());
        List<TWarehousebillsfees> warehousebillsfees = warehousebillsfeesMapper.selectTWarehousebillsfeesList(tWarehousebillsfees);
        if (CollectionUtils.isNotEmpty(warehousebillsfees)) {
            warehousebillsModifyVO.settWarehousebillsfees(warehousebillsfees);
        }
        return warehousebillsModifyVO;
    }

    /**
     * 查询仓库主(出入库)列表
     *
     * @param warehousebillsModifyDto 查询条件
     * @return 仓库主(出入库)
     */
    @Override
    public List<TWarehousebillsModify> selectTWarehousebillsModifyList(WarehousebillsModifyDTO warehousebillsModifyDto) {
        // 查询列表信息
        List<TWarehousebillsModify> warehousebillsModifyList = tWarehousebillsModifyMapper.selectTWarehousebillsModifyList(warehousebillsModifyDto);
        if (CollectionUtils.isNotEmpty(warehousebillsModifyList)) {
            // 取出客户集合信息
            List<Long> corpIds = warehousebillsModifyList.stream().filter(li -> Objects.nonNull(li.getfCorpid()))
                    .map(TWarehousebillsModify::getfCorpid).distinct().collect(Collectors.toList());
            List<TCorps> corpsList = Collections.emptyList();
            if (CollectionUtils.isNotEmpty(corpIds)) {
                corpsList = corpsMapper.selectByIds(corpIds);
            }
            // 遍历赋值汉字
            for (TWarehousebillsModify vo : warehousebillsModifyList) {
                // 过滤客户信息
                Optional<TCorps> corpFirst = corpsList.stream().filter(li -> Objects.equals(li.getfId(), vo.getfCorpid())).findFirst();
                corpFirst.ifPresent(tCorps -> vo.setCorpName(tCorps.getfName()));
            }
        }
        return warehousebillsModifyList;
    }

    /**
     * 暂存
     *
     * @param tWarehousebillsModify 仓库主(出入库)
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult saveTWarehousebillsModify(WarehousebillsModifyDTO tWarehousebillsModify) {
        // 获取当前登陆人
        String username = SecurityUtils.getUsername();
        // 赋值上级id
        tWarehousebillsModify.setfPid(tWarehousebillsModify.getWarehouseId());
        if (Objects.isNull(tWarehousebillsModify.getfId())) {
            // 获取编号
            String billNo = billnoSerialService.getBillNo(WarehouseTypeEnum.FYBG_NO.getType(), new Date());
            tWarehousebillsModify.setfBillno(billNo);
            tWarehousebillsModify.setCreateBy(username);
            tWarehousebillsModify.setCreateTime(new Date());
            tWarehousebillsModify.setfStatus(FeesTypeEnum.SAVE.getType());
            tWarehousebillsModifyMapper.insertTWarehousebillsModify(tWarehousebillsModify);
        } else {
            tWarehousebillsModify.setUpdateTime(new Date());
            tWarehousebillsModify.setUpdateBy(username);
            tWarehousebillsModifyMapper.updateTWarehousebillsModify(tWarehousebillsModify);
        }
        // 追加费用信息
        List<TWarehousebillsfeesModify> feesItemList = tWarehousebillsModify.getItems();
        feesItemList.forEach(li -> {
            li.setfPid(tWarehousebillsModify.getfId());
            li.setfMblno(tWarehousebillsModify.getfMblno());
            li.setfSrcTypeId(Integer.parseInt(FeesTypeEnum.FEE_CHANGES.getType()));
            if (Objects.isNull(li.getfId())) {
                li.setCreateTime(new Date());
                li.setCreateBy(username);
                tWarehousebillsfeesModifyMapper.insertTWarehousebillsfeesModify(li);
            } else {
                li.setUpdateTime(new Date());
                li.setUpdateBy(username);
                tWarehousebillsfeesModifyMapper.updateTWarehousebillsfeesModify(li);
            }
        });
        return AjaxResult.success(tWarehousebillsModify);
    }

    /**
     * 请核
     *
     * @param tWarehousebillsModify 仓库主(出入库)
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult submitTWarehousebillsModify(WarehousebillsModifyDTO tWarehousebillsModify) {
        // 获取当前登陆人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String username = loginUser.getUsername();
        // 赋值上级id
        tWarehousebillsModify.setfPid(tWarehousebillsModify.getWarehouseId());
        SysConfig sysConfig = sysConfigMapper.checkConfigKeyUnique("warehouse.costModify.ApprovalFlow");
        boolean isAudit = Objects.nonNull(sysConfig) && "0".equals(sysConfig.getConfigValue());
        tWarehousebillsModify.setfStatus(FeesTypeEnum.SUBMIT.getType());
        if (Objects.isNull(tWarehousebillsModify.getfId())) {
            // 获取编号
            String billNo = billnoSerialService.getBillNo(WarehouseTypeEnum.FYBG_NO.getType(), new Date());
            tWarehousebillsModify.setfBillno(billNo);
            tWarehousebillsModify.setCreateTime(new Date());
            tWarehousebillsModify.setCreateBy(username);
            tWarehousebillsModifyMapper.insertTWarehousebillsModify(tWarehousebillsModify);
        } else {
            tWarehousebillsModify.setUpdateTime(new Date());
            tWarehousebillsModify.setUpdateBy(username);
            tWarehousebillsModifyMapper.updateTWarehousebillsModify(tWarehousebillsModify);
        }
        // 删除需要删除的子订单
        if (CollectionUtils.isNotEmpty(tWarehousebillsModify.getItemDels())) {
            tWarehousebillsfeesModifyMapper.deleteTWarehousebillsfeesModifyByIds(tWarehousebillsModify.getItemDels());
        }
        // 追加费用信息
        List<TWarehousebillsfeesModify> feesItemList = tWarehousebillsModify.getItems();
        feesItemList.forEach(li -> {
            li.setfPid(tWarehousebillsModify.getfId());
            li.setfMblno(tWarehousebillsModify.getfMblno());
            li.setfSrcTypeId(Integer.parseInt(FeesTypeEnum.FEE_CHANGES.getType()));
            li.setfStatus(Long.parseLong(tWarehousebillsModify.getfStatus()));
            if (Objects.isNull(li.getfId())) {
                li.setCreateTime(new Date());
                li.setCreateBy(username);
                tWarehousebillsfeesModifyMapper.insertTWarehousebillsfeesModify(li);
            } else {
                li.setUpdateTime(new Date());
                li.setUpdateBy(username);
                tWarehousebillsfeesModifyMapper.updateTWarehousebillsfeesModify(li);
            }
        });
        // 是否需要启用审批流
        if (isAudit) {
            initiateApprovalFlow(tWarehousebillsModify, loginUser);
            return AjaxResult.success();
        }
        // 直接算作审核完成
        additionalFeeInformation(tWarehousebillsModify.getfId(), WarehouseTypeEnum.APPROVE);

        return AjaxResult.success();
    }

    /**
     * 根据id追加对应仓库费用信息
     *
     * @param id       费用变更主表id
     * @param typeEnum 更新状态
     */
    public void additionalFeeInformation(Long id, WarehouseTypeEnum typeEnum) {
        // 查询费用变更主表
        TWarehousebillsModify warehousebillsModify = tWarehousebillsModifyMapper.selectTWarehousebillsModifyById(id);
        if (Objects.isNull(warehousebillsModify)) {
            throw new WarehouseException("找不到费用变更信息");
        }
        // 更新主表状态
        warehousebillsModify.setUpdateTime(new Date());
        warehousebillsModify.setUpdateBy(SecurityUtils.getUsername());
        warehousebillsModify.setfStatus(typeEnum.getType());
        tWarehousebillsModifyMapper.updateTWarehousebillsModify(warehousebillsModify);
        // 查询费用变更明细表数据
        TWarehousebillsfeesModify tWarehousebillsfeesModify = new TWarehousebillsfeesModify();
        tWarehousebillsfeesModify.setfPid(id);
        List<TWarehousebillsfeesModify> feesList = tWarehousebillsfeesModifyMapper.selectTWarehousebillsfeesModifyList(tWarehousebillsfeesModify);
        feesList.forEach(li -> {
            // 更新明细表状态
            li.setUpdateTime(new Date());
            li.setfReviewDate(new Date());
            li.setUpdateBy(SecurityUtils.getUsername());
            li.setfStatus(Long.parseLong(typeEnum.getType()));
            li.setfBillstatus(Long.parseLong(typeEnum.getType()));
            if (typeEnum.getType().equals(WarehouseTypeEnum.APPROVE.getType())) {
                // 往仓储费用表追加数据
                TWarehousebillsfees warehousebillsfees = new TWarehousebillsfees();
                BeanUtils.copyProperties(li, warehousebillsfees);
                warehousebillsfees.setfId(null);
                warehousebillsfees.setfStatus(typeEnum.getType());
                warehousebillsfees.setfPid(warehousebillsModify.getfPid());
                warehousebillsfees.setfSrcTypeId(Long.parseLong(FeesTypeEnum.FEE_CHANGES.getType()));
                // 制空内容
                warehousebillsfees.setfAccamount(BigDecimal.ZERO);
                warehousebillsfees.setfAskamount(BigDecimal.ZERO);
                warehousebillsfees.setfInvamount(BigDecimal.ZERO);
                warehousebillsfees.setfStlamount(BigDecimal.ZERO);
                warehousebillsfees.setfAccamountDate(null);
                warehousebillsfees.setfStatementNo(null);
                warehousebillsfees.setfStlamountNo(null);
                warehousebillsfees.setfInvnos(null);
                warehousebillsfeesMapper.insertTWarehousebillsfees(warehousebillsfees);
                li.setSrcId(warehousebillsfees.getfId());
            }
            tWarehousebillsfeesModifyMapper.updateTWarehousebillsfeesModify(li);
        });
    }

    /**
     * 费用变更发起审批流
     *
     * @param tWarehousebillsModify 费用变更信息
     * @param loginUser             当前登录用户
     */
    private void initiateApprovalFlow(WarehousebillsModifyDTO tWarehousebillsModify, LoginUser loginUser) {
        AuditItems auditItems = new AuditItems();
        auditItems.setLevelId(0L);
        auditItems.setBillId(tWarehousebillsModify.getfId());
        auditItems.setActId(WarehouseActIdEnum.FEE_CHANGES.getActId().longValue());
        auditItems.setIffinalItem("F");
        auditItems.setBillNo(tWarehousebillsModify.getfBillno());
        auditItems.setRefno1(tWarehousebillsModify.getfCorpid().toString());
        auditItems.setRefno2(WarehouseTypeEnum.FYBG_NO.getType());
        auditItems.setRefno3(tWarehousebillsModify.getfBillno());
        auditItems.setSendUserId(loginUser.getUser().getUserId());
        auditItems.setSendName(loginUser.getUsername());
        auditItems.setSendTime(new Date());
        auditItems.setAuditUserId(loginUser.getUser().getUserId());
        auditItems.setAuditItem(new Date());
        auditItems.setAuditOpTime(new Date());
        auditItems.setAuditMsg("提交");
        auditItems.setAuditStatus("O");
        auditItems.setFidStatus("f_status");
        AjaxResult approvalFlow = auditItemsService.createApprovalFlow(auditItems);
        String code = approvalFlow.get("code").toString();
        if ("500".equals(code)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 批量删除仓库主(出入库)
     *
     * @param fIds 需要删除的仓库主(出入库)ID
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteTWarehousebillsModifyByIds(String fIds) {
        List<Long> ids = Arrays.asList(toLongArray(fIds));
        if (CollectionUtils.isEmpty(ids)) {
            throw new WarehouseException("缺少删除参数");
        }
        // 判断这些状态是否存在不为暂存的
        long count = tWarehousebillsfeesModifyMapper.selectStatusByIds(ids).stream()
                .filter(li -> FeesTypeEnum.fromType(String.valueOf(li.getfStatus())).isDelete()).count();
        if (count > 0) {
            throw new WarehouseException("删除数据状态不对");
        }
        // 查出需要回收的编号
        List<String> billNos = tWarehousebillsModifyMapper.selectBillNoByIds(ids);
        billNos.forEach(no -> {
            // 2、业务编号、客存编号 放入 billno_del
            BillnoDel billnoDel = new BillnoDel();
            billnoDel.setBillType(WarehouseTypeEnum.SJRK_NO.getType());
            billnoDel.setBillNo(no);
            billnoDelMapper.insertBillnoDel(billnoDel);
        });
        tWarehousebillsModifyMapper.deleteTWarehousebillsModifyByIds(ids);
        tWarehousebillsfeesModifyMapper.deleteByPid(ids);
        return AjaxResult.success();
    }

    /**
     * 删除仓库主(出入库)信息
     *
     * @param fId 仓库主(出入库)ID
     * @return 结果
     */
    @Override
    public int deleteTWarehousebillsModifyById(Long fId) {
        return tWarehousebillsModifyMapper.deleteTWarehousebillsModifyById(fId);
    }

    /**
     * 根据仓库id、费用类型查询费用信息
     *
     * @param fId  仓库id
     * @param type 费用类型
     * @return
     */
    @Override
    public AjaxResult selectTWarehousebillsFeesById(Long fId, String type) {
        // 查询仓储信息
        TWarehouseBills warehouseBills = warehousebillsmapper.selectTWarehousebillsById(fId);
        // 如果未查出仓储信息或仓储状态为未审核通过则抛出异常
        if (Objects.isNull(warehouseBills) || Objects.equals(warehouseBills.getfBillstatus(), WarehouseTypeEnum.APPROVE.getType())) {
            throw new WarehouseException("未找到仓储信息或仓储信息未审核通过");
        }
        WarehousebillsModifyVO modifyVO = new WarehousebillsModifyVO();
        // 查询所有费用信息
        TWarehousebillsfees warehousebillsfees = new TWarehousebillsfees();
        warehousebillsfees.setfPid(fId);
        warehousebillsfees.setfDc(type);
        List<TWarehousebillsfees> feesList = warehousebillsfeesMapper.selectTWarehousebillsfeesList(warehousebillsfees);
        if (CollectionUtils.isNotEmpty(feesList)) {
            modifyVO.settWarehousebillsfees(feesList);
        }
        // 组装主表字段
        modifyVO.setfPid(warehouseBills.getfId());
        modifyVO.setfMblno(warehouseBills.getfMblno());
        modifyVO.setfMarks(warehouseBills.getfMarks());
        modifyVO.setfCorpid(warehouseBills.getfCorpid());
        modifyVO.setfBstime(warehouseBills.getfBsdate());
        modifyVO.setfGoodsid(warehouseBills.getfProductName());
        modifyVO.setfBilltype(warehouseBills.getfBilltype());
        modifyVO.setfWarehouseid(warehouseBills.getfWarehouseid());
        // 转化客户、商品、仓库名称
        TCorps tCorps = corpsMapper.selectTCorpsById(modifyVO.getfCorpid());
        if (Objects.nonNull(tCorps)) {
            modifyVO.setCorpName(tCorps.getfName());
        }
        TWarehouse tWarehouse = warehouseMapper.selectTWarehouseById(modifyVO.getfWarehouseid());
        if (Objects.nonNull(tWarehouse)) {
            modifyVO.setWarehouseName(tWarehouse.getfName());
        }

        return AjaxResult.success(modifyVO);
    }

    /**
     * 已经审核完成，要撤回
     *
     * @param id 主表id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult revokeReviewedById(Long id) {
        TWarehousebillsModify warehousebillsModify = tWarehousebillsModifyMapper.selectTWarehousebillsModifyById(id);
        if (Objects.isNull(warehousebillsModify) || !warehousebillsModify.getfStatus().equals(FeesTypeEnum.APPROVE.getType())) {
            throw new WarehouseException("无效id或未审核完成");
        }
        List<TWarehousebillsfeesModify> warehousebillsfeesModifies = tWarehousebillsfeesModifyMapper.selectListByPid(id);
        warehousebillsfeesModifies.forEach(li -> {
            warehousebillsfeesMapper.deleteTWarehousebillsfeesById(li.getSrcId());
        });
        warehousebillsModify.setfStatus(FeesTypeEnum.SAVE.getType());
        warehousebillsModify.setUpdateTime(new Date());
        warehousebillsModify.setUpdateBy(SecurityUtils.getUsername());
        tWarehousebillsModifyMapper.updateTWarehousebillsModify(warehousebillsModify);
        return AjaxResult.success();
    }

    /**
     * 撤回已提交的审批
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void withdrawalApprovalById(Long id) {
        TWarehousebillsModify warehousebillsModify = tWarehousebillsModifyMapper.selectTWarehousebillsModifyById(id);
        if (Objects.isNull(warehousebillsModify)) {
            throw new WarehouseException("无效id");
        }
        List<TWarehousebillsfeesModify> warehousebillsfeesModifies = tWarehousebillsfeesModifyMapper.selectListByPid(id);

        long count = warehousebillsfeesModifies.stream()
                .filter(item -> !Objects.equals(item.getfStatus(), Long.parseLong(FeesTypeEnum.SUBMIT.getType())))
                .count();
        if (count > 0) {
            throw new WarehouseException("该请核已被操作");
        }
        // 获取当前登陆人
        String username = SecurityUtils.getUsername();
        // 更新主表
        warehousebillsModify.setUpdateBy(username);
        warehousebillsModify.setUpdateTime(new Date());
        warehousebillsModify.setfStatus(FeesTypeEnum.SAVE.getType());
        tWarehousebillsModifyMapper.updateTWarehousebillsModify(warehousebillsModify);
        // 更新明细表
        warehousebillsfeesModifies.forEach(li -> {
            li.setUpdateBy(username);
            li.setUpdateTime(new Date());
            li.setfStatus(Long.parseLong(FeesTypeEnum.SAVE.getType()));
            tWarehousebillsfeesModifyMapper.updateTWarehousebillsfeesModify(li);
        });
    }

}
