package cn.iocoder.yudao.module.asset.service.assetreceiveinfo;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.asset.controller.admin.assetreceiveinfo.vo.AssetReceiveInfoPageReqVO;
import cn.iocoder.yudao.module.asset.controller.admin.assetreceiveinfo.vo.AssetReceiveInfoSaveReqVO;
import cn.iocoder.yudao.module.asset.controller.admin.assetreceiveinfo.vo.AssetReceiveInfoUpdateReqVO;
import cn.iocoder.yudao.module.asset.dal.dataobject.assetinfo.AssetInfoDO;
import cn.iocoder.yudao.module.asset.dal.dataobject.assetreceiveinfo.AssetReceiveInfoDO;
import cn.iocoder.yudao.module.asset.dal.mysql.assetreceiveinfo.AssetReceiveInfoMapper;
import cn.iocoder.yudao.module.asset.enums.AssetReturnStateEnum;
import cn.iocoder.yudao.module.asset.enums.AssetStateEnum;
import cn.iocoder.yudao.module.asset.service.assetinfo.AssetInfoService;
import cn.iocoder.yudao.module.employee.api.EmployeeApi;
import cn.iocoder.yudao.module.employee.api.dto.EmployeeRespDTO;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.asset.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.employee.enums.ErrorCodeConstants.EMPLOYEE_INFO_NOT_EXISTS;

/**
 * 固定资产领用信息 Service 实现类
 *
 * @author dp
 */
@Service
@Validated
public class AssetReceiveInfoServiceImpl implements AssetReceiveInfoService {

    @Resource
    private AssetReceiveInfoMapper receiveInfoMapper;

    @Resource
    private AssetInfoService assetInfoService;

    @Resource
    private EmployeeApi employeeApi;

    @Resource
    private DeptApi deptApi;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createReceiveInfo(AssetReceiveInfoSaveReqVO createReqVO) {
        // 登录人
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        EmployeeRespDTO loginEmployee = employeeApi.getEmployeeByUserId(loginUserId);
        if (Objects.isNull(loginEmployee)) {
            throw exception(new ErrorCode(EMPLOYEE_INFO_NOT_EXISTS.getCode(), "当前登录人员无员工信息"));
        }
        Long assetInfoId = createReqVO.getAssetInfoId();
        AssetInfoDO assetInfoDO = assetInfoService.getInfo(assetInfoId);
        if (Objects.isNull(assetInfoDO)) {
            throw exception(INFO_NOT_EXISTS);
        }
        if (!AssetStateEnum.AVAILABLE.getState().equals(assetInfoDO.getAssetState())) {
            throw exception(ASSET_INFO_NOT_AVAILABLE);
        }
        Long employeeId = createReqVO.getEmployeeId();
        if (Objects.isNull(employeeId)) {
            throw exception(ASSET_RECEIVE_EMPLOYEE_NOT_NULL);
        }
        String receiveDate = createReqVO.getReceiveDate();
        if (StrUtil.isBlank(receiveDate)) {
            throw exception(ASSET_RECEIVE_DATE_NOT_BLANK);
        }
        if (StrUtil.isBlank(createReqVO.getReason())) {
            throw exception(ASSET_RECEIVE_REASON_NOT_BLANK);
        }
        // 插入
        AssetReceiveInfoDO receiveInfo = BeanUtils.toBean(createReqVO, AssetReceiveInfoDO.class);
        // uuid
        receiveInfo.setReceiveInfoUuid(IdUtil.fastSimpleUUID());
        // 资产名称
        receiveInfo.setAssetInfoName(assetInfoDO.getName());
        // 未归还
        receiveInfo.setReturned(AssetReturnStateEnum.NOT_RETURNED.getState());
        // 创建人
        receiveInfo.setCreator(String.valueOf(loginEmployee.getId()));
        // 操作人
        receiveInfo.setUpdater(String.valueOf(loginEmployee.getId()));
        // 部门
        receiveInfo.setDeptId(loginEmployee.getDeptId());
        // 职位
        receiveInfo.setPostId(loginEmployee.getPostId());
        receiveInfoMapper.insert(receiveInfo);

        // 领用成功后修改资产状态
        AssetInfoDO build = AssetInfoDO.builder()
                .id(assetInfoId)
                .receiveEmployeeId(receiveInfo.getEmployeeId())
                .receiveInfoId(receiveInfo.getId())
                .assetState(AssetStateEnum.OCCUPIED.getState())
                .build();
        assetInfoService.availableOrOccupiedAssetInfo(build);
        // 返回
        return receiveInfo.getId();
    }

    @Override
    public void updateReceiveInfo(AssetReceiveInfoUpdateReqVO updateReqVO) {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        EmployeeRespDTO loginEmployee = employeeApi.getEmployeeByUserId(loginUserId);

        AssetInfoDO assetInfoDO = assetInfoService.getInfo(updateReqVO.getAssetInfoId());
        if (Objects.isNull(assetInfoDO)) {
            throw exception(INFO_NOT_EXISTS);
        }
        if (!AssetStateEnum.OCCUPIED.getState().equals(assetInfoDO.getAssetState())) {
            throw exception(ASSET_INFO_NOT_OCCUPIED);
        }

        Long receiveInfoId = assetInfoDO.getReceiveInfoId();
        // 校验存在
        AssetReceiveInfoDO assetReceiveInfoDO = validateReceiveInfoExists(receiveInfoId);
        String returnDate = updateReqVO.getReturnDate();
        if (StrUtil.isBlank(returnDate)) {
            throw exception(ASSET_RETURN_DATE_NOT_BLANK);
        }
        String returnReason = updateReqVO.getReturnReason();
        if (StrUtil.isBlank(returnReason)) {
            throw exception(ASSET_RETURN_REASON_NOT_BLANK);
        }
        // 更新
        AssetReceiveInfoDO updateObj = BeanUtils.toBean(updateReqVO, AssetReceiveInfoDO.class);
        // 已归还
        updateObj.setReturned(AssetReturnStateEnum.RETURNED.getState());
        // 操作人
        updateObj.setUpdater(String.valueOf(loginEmployee.getId()));
        updateObj.setId(receiveInfoId);
        receiveInfoMapper.updateById(updateObj);

        // 更新对应资产状态为可用，同时置空领用信息
        AssetInfoDO build = AssetInfoDO.builder()
                .id(assetInfoDO.getId())
                .assetState(AssetStateEnum.AVAILABLE.getState())
                .receiveEmployeeId(null)
                .receiveInfoId(null)
                .build();
        assetInfoService.availableOrOccupiedAssetInfo(build);
    }

    @Override
    public void deleteReceiveInfo(Long id) {
        // 校验存在
        validateReceiveInfoExists(id);
        // 删除
        receiveInfoMapper.deleteById(id);
    }

    private AssetReceiveInfoDO validateReceiveInfoExists(Long id) {
        AssetReceiveInfoDO assetReceiveInfoDO = receiveInfoMapper.selectById(id);
        if (assetReceiveInfoDO == null) {
            throw exception(RECEIVE_INFO_NOT_EXISTS);
        }
        return assetReceiveInfoDO;
    }

    @Override
    public AssetReceiveInfoDO getReceiveInfo(Long id) {
        return receiveInfoMapper.selectById(id);
    }

    @Override
    public PageResult<AssetReceiveInfoDO> getReceiveInfoPage(AssetReceiveInfoPageReqVO pageReqVO) {
        return receiveInfoMapper.selectPage(pageReqVO);
    }

}