package com.hys.app.service.erp.impl;

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.hys.app.framework.context.user.AdminUserContext;
import com.hys.app.framework.database.WebPage;
import com.hys.app.framework.exception.ServiceException;
import com.hys.app.framework.security.model.Admin;
import com.hys.app.framework.util.BeanUtil;
import com.hys.app.framework.util.DateUtil;
import com.hys.app.framework.util.PageConvert;
import com.hys.app.framework.util.StringUtil;
import com.hys.app.mapper.erp.LendFormMapper;
import com.hys.app.model.erp.dos.LendForm;
import com.hys.app.model.erp.dos.LendFormProduct;
import com.hys.app.model.erp.dto.LendFormDTO;
import com.hys.app.model.erp.dto.LendFormQueryParam;
import com.hys.app.model.erp.dto.LendFormReturnDTO;
import com.hys.app.model.erp.enums.LendFormStatusEnum;
import com.hys.app.model.erp.enums.NoBusinessTypeEnum;
import com.hys.app.model.erp.vo.LendFormAllowable;
import com.hys.app.model.erp.vo.LendFormVO;
import com.hys.app.service.erp.LendFormManager;
import com.hys.app.service.erp.LendFormProductManager;
import com.hys.app.service.erp.NoGenerateManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 商品借出单业务接口实现
 * @author dmy
 * 2023-12-05
 */
@Service
public class LendFormManagerImpl extends ServiceImpl<LendFormMapper, LendForm> implements LendFormManager {

    @Autowired
    private NoGenerateManager noGenerateManager;

    @Autowired
    private LendFormProductManager lendFormProductManager;

    /**
     * 查询商品借出单分页列表数据
     *
     * @param params 查询参数
     * @return
     */
    @Override
    public WebPage list(LendFormQueryParam params) {
        IPage<LendForm> iPage = this.lambdaQuery()
                .like(StringUtil.notEmpty(params.getSn()), LendForm::getSn, params.getSn())
                .eq(params.getWarehouseId() != null, LendForm::getWarehouseId, params.getWarehouseId())
                .eq(StringUtil.notEmpty(params.getStatus()), LendForm::getStatus, params.getStatus())
                .eq(params.getDeptId() != null, LendForm::getDeptId, params.getDeptId())
                .gt(params.getStartTime() != null, LendForm::getLendTime, params.getStartTime())
                .lt(params.getEndTime() != null, LendForm::getLendTime, params.getEndTime())
                .orderByDesc(LendForm::getCreateTime)
                .page(new Page<>(params.getPageNo(), params.getPageSize()));
        //设置借出单运行的操作
        for (LendForm record : iPage.getRecords()) {
            LendFormAllowable allowable = new LendFormAllowable(record);
            record.setAllowable(allowable);
        }
        return PageConvert.convert(iPage);
    }

    /**
     * 新增商品借出单
     *
     * @param lendFormDTO 商品借出单信息
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void add(LendFormDTO lendFormDTO) {
        //构建商品借出单信息
        LendForm lendForm = new LendForm();
        BeanUtil.copyProperties(lendFormDTO, lendForm);
        //生成商品借出单编号
        String sn = noGenerateManager.generate(NoBusinessTypeEnum.LendForm);
        lendForm.setSn(sn);
        //设置创建时间
        lendForm.setCreateTime(DateUtil.getDateline());
        //设置状态默认为新创建
        lendForm.setStatus(LendFormStatusEnum.NEW.name());
        //入库
        this.save(lendForm);
        //获取主键ID
        Long id = lendForm.getId();
        //保存商品信息
        this.lendFormProductManager.saveProduct(id, lendFormDTO.getProductList());
    }

    /**
     * 编辑商品借出单
     *
     * @param id 主键ID
     * @param lendFormDTO 商品借出单信息
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void edit(Long id, LendFormDTO lendFormDTO) {
        //获取商品借出单旧数据
        LendForm lendForm  = this.getById(id);
        if (!LendFormStatusEnum.NEW.name().equals(lendForm.getStatus())) {
            throw new ServiceException("只有状态为新创建的商品借出单才可以进行编辑操作");
        }
        //复制修改后的数据
        BeanUtil.copyProperties(lendFormDTO, lendForm);
        //修改商品借出单信息
        this.updateById(lendForm);
        //入库借出单商品
        this.lendFormProductManager.saveProduct(id, lendFormDTO.getProductList());
    }

    /**
     * 删除商品借出单
     *
     * @param ids 商品借出单主键ID集合
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void delete(List<Long> ids) {
        List<LendForm> forms = this.lambdaQuery()
                .in(LendForm::getId, ids)
                .list();
        if (forms == null || forms.size() == 0) {
            throw new ServiceException("要删除的商品借出单不存在");
        }
        //验证借出单状态是否可以删除
        for (LendForm form : forms) {
            if (!LendFormStatusEnum.NEW.name().equals(form.getStatus())) {
                throw new ServiceException("只有状态为新创建的商品借出单才可进行删除操作");
            }
        }
        //批量删除商品借出单
        this.removeByIds(ids);
        //删除借出单商品信息
        this.lendFormProductManager.deleteProduct(ids);
    }

    /**
     * 获取商品借出单详情
     *
     * @param id 主键ID
     * @return
     */
    @Override
    public LendFormVO getDetail(Long id) {
        LendForm lendForm = this.getById(id);
        LendFormVO lendFormVO = new LendFormVO();
        BeanUtil.copyProperties(lendForm, lendFormVO);

        //获取借出单商品信息
        List<LendFormProduct> goodsList = this.lendFormProductManager.list(id);
        lendFormVO.setProductList(goodsList);
        return lendFormVO;
    }

    /**
     * 确认商品借出单
     *
     * @param ids 商品借出单主键ID集合
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void confirm(List<Long> ids) {
        List<LendForm> forms = this.lambdaQuery()
                .in(LendForm::getId, ids)
                .list();
        if (forms == null || forms.size() == 0) {
            throw new ServiceException("要确认的商品借出单不存在");
        }
        //获取当前登录的管理员信息
        Admin admin = AdminUserContext.getAdmin();
        //验证借出单状态是否可以确认
        for (LendForm form : forms) {
            if (!LendFormStatusEnum.NEW.name().equals(form.getStatus())) {
                throw new ServiceException("只有状态为新创建的商品借出单才可进行确认操作");
            }
            //判断当前确认借出单的管理员是否为借出人
            if (!admin.getUid().equals(form.getLendPersonId())) {
                throw new ServiceException("编号为[" + form.getSn() + "]的借出单的出借人与当前的确认人不符，无法进行确认操作");
            }
        }
        //修改商品借出单状态为已确认
        this.lambdaUpdate()
                .set(LendForm::getStatus, LendFormStatusEnum.CONFIRMED.name())
                .set(LendForm::getConfirmTime, DateUtil.getDateline())
                .in(LendForm::getId, ids)
                .update();
    }

    /**
     * 商品借出单产品归还
     *
     * @param id 主键ID
     * @param lendFormReturnDTO 商品借出单产品归还信息
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void returnProduct(Long id, LendFormReturnDTO lendFormReturnDTO) {
        //获取商品借出单信息
        LendForm lendForm = this.getById(id);
        if (!LendFormStatusEnum.CONFIRMED.name().equals(lendForm.getStatus())) {
            throw new ServiceException("只有状态为已确认的商品借出单才可进行归还操作");
        }
        //设置商品归还信息
        lendForm.setReturnPersonId(lendFormReturnDTO.getReturnPersonId());
        lendForm.setReturnPerson(lendFormReturnDTO.getReturnPerson());
        lendForm.setReturnRegisterId(lendFormReturnDTO.getReturnRegisterId());
        lendForm.setReturnRegister(lendFormReturnDTO.getReturnRegister());
        lendForm.setReturnTime(lendFormReturnDTO.getReturnTime());
        lendForm.setReturnDesc(lendFormReturnDTO.getReturnDesc());
        //修改借出单状态为已归还
        lendForm.setStatus(LendFormStatusEnum.RETURNED.name());
        this.updateById(lendForm);

        //修改借出单产品归还数量
        this.lendFormProductManager.updateProductReturnNum(lendFormReturnDTO.getProductList());
    }
}
