package com.zd.chemical.service.impl;

import com.zd.chemical.domain.*;
import com.zd.chemical.domain.vo.*;
import com.zd.chemical.mapper.HxpAlarmRecordMapper;
import com.zd.chemical.mapper.HxpCabinetlockLogMapper;
import com.zd.chemical.mapper.HxpStockMapper;
import com.zd.chemical.mapper.HxpUserecordMapper;
import com.zd.chemical.service.IHxpClassifyConfigService;
import com.zd.chemical.service.IHxpUserecordService;
import com.zd.common.core.constant.HttpStatus;
import com.zd.common.core.constant.SecurityConstants;
import com.zd.common.core.domain.R;
import com.zd.common.core.domain.per.PerPrefix;
import com.zd.common.core.exception.ServiceException;
import com.zd.common.core.utils.DateUtils;
import com.zd.common.core.utils.SecurityUtils;
import com.zd.common.core.utils.StringUtils;
import com.zd.common.datascope.annotation.DataScope;
import com.zd.common.security.utils.SaveUtil;
import com.zd.system.api.RemoteUserService;
import com.zd.system.api.domain.SysUser;
import com.zd.system.api.face.FaceCompare;
import com.zd.system.api.face.RemoteFaceService;
import com.zd.system.api.laboratory.RemoteMessageContentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 化学品使用记录Service业务层处理
 *
 * @author liubo
 * @date 2022-06-18
 */
@Service
public class HxpUserecordServiceImpl implements IHxpUserecordService {
    private Logger logger = LoggerFactory.getLogger(HxpUserecordServiceImpl.class);

    @Autowired
    private HxpUserecordMapper hxpUserecordMapper;
    @Autowired
    private HxpStockMapper hxpStockMapper;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private IHxpClassifyConfigService hxpClassifyConfigService;
    @Autowired
    private RemoteFaceService remoteFaceService;
    @Autowired
    private RemoteMessageContentService remoteMessageContentService;
    @Autowired
    private HxpAlarmRecordMapper hxpAlarmRecordMapper;
    @Autowired
    private HxpCabinetlockLogMapper hxpCabinetlockLogMapper;

    /**
     * 查询化学品使用记录
     *
     * @param id 化学品使用记录主键
     * @return 化学品使用记录
     */
    @Override
    public HxpUserecord selectHxpUserecordById(Long id) {
        return hxpUserecordMapper.selectHxpUserecordById(id);
    }

    /**
     * 查询化学品使用记录列表
     *
     * @param hxpUserecord 化学品使用记录
     * @return 化学品使用记录
     */
    @Override
    public List<HxpUserecord> selectHxpUserecordList(HxpUserecord hxpUserecord) {
        return hxpUserecordMapper.selectHxpUserecordList(hxpUserecord);
    }

    /**
     * 查询化学品使用记录列表
     *
     * @param hxpUserecordSearch 化学品使用记录
     * @return 化学品使用记录
     */
    @Override
    @DataScope(deptAlias = "st", permi = PerPrefix.HXP_USERECORD)
    public List<HxpUserecordVo> getHxpUserecordList(HxpUserecordSearch hxpUserecordSearch) {
        return hxpUserecordMapper.getHxpUserecordList(hxpUserecordSearch);
    }

    /**
     * 新增化学品使用记录
     *
     * @param hxpUserecord 化学品使用记录
     * @return 结果
     */
    @Override
    public HxpUserecord insertHxpUserecord(HxpUserecord hxpUserecord) {

        HxpStock hxpStock = hxpStockMapper.selectHxpStockById(hxpUserecord.getStockId());
        if(hxpStock == null){
            throw new ServiceException("数据无效，操作失败！");
        }
        // 判断该化学品当前是否处于领用状态
        HxpUserecord oldUserecord = new HxpUserecord();
        oldUserecord.setStockId(hxpUserecord.getStockId());
        oldUserecord.setUseStatus(1);
        List<HxpUserecord> list = hxpUserecordMapper.selectHxpUserecordList(oldUserecord);
        if(list.size() > 0){
            throw new ServiceException("该化学品已被领用，领用失败！");
        }

        HxpClassifyConfig hxpClassifyConfig = hxpClassifyConfigService.selectHxpClassifyConfigById(hxpStock.getChemicalClassify());
        if(hxpClassifyConfig != null && hxpClassifyConfig.getCollectStatus() == 2){
            if((hxpUserecord.getOutOneUser() == null || hxpUserecord.getOutTwoUser() == null)){
                throw new ServiceException("领用该化学品需要双人验证，请先完成验证！");
            }
        }
        if(hxpUserecord.getOutOneUser() == null){
            hxpUserecord.setOutOneUser(SecurityUtils.getUserId());
        }

        /*if(!Objects.equals(hxpStock.getOutUsages(), hxpUserecord.getCollectStockNum())){
            throw new ServiceException("当前库存量与实际不符，请联系管理员！");
        }*/
        hxpUserecord.setCollectNowNum(hxpStock.getOutUsages());
        hxpUserecord.setLossAmount(hxpStock.getOutUsages().subtract(hxpUserecord.getCollectStockNum()));

        //设置其他公共字段
        SaveUtil.setCommonAttr(hxpUserecord);
        hxpUserecord.setCollectTime(DateUtils.getNowDate());
        hxpUserecord.setUseStatus(1);
        hxpUserecordMapper.insertHxpUserecord(hxpUserecord);

        if(hxpUserecord.getLockLogId() != null){
            HxpCabinetlockLog hxpCabinetlockLog = new HxpCabinetlockLog();
            hxpCabinetlockLog.setId(hxpUserecord.getLockLogId());
            hxpCabinetlockLog.setUserecordId(hxpUserecord.getId());
            hxpCabinetlockLogMapper.updateHxpCabinetlockLog(hxpCabinetlockLog);
        }

        return hxpUserecord;
    }

    /**
     * 修改化学品使用记录
     *
     * @param hxpUserecord 化学品使用记录
     * @return 结果
     */
    @Override
    @Transactional
    public HxpUserecord updateHxpUserecord(HxpUserecord hxpUserecord) {

        HxpUserecord oldUserecord = hxpUserecordMapper.selectHxpUserecordById(hxpUserecord.getId());
        if(oldUserecord == null){
            throw new ServiceException("ID无效，请重试！");
        }
        if(oldUserecord.getUseStatus() != 1){
            throw new ServiceException("该化学品不是领用状态，不能归还！");
        }
        if(!Objects.equals(oldUserecord.getUserId(), SecurityUtils.getUserId())){
            throw new ServiceException("当前归还人不是领用人，无法操作！");
        }
        HxpStock hxpStock = hxpStockMapper.selectHxpStockById(oldUserecord.getStockId());

        HxpClassifyConfig hxpClassifyConfig = hxpClassifyConfigService.selectHxpClassifyConfigById(hxpStock.getChemicalClassify());
        if(hxpClassifyConfig != null && hxpClassifyConfig.getReturnStatus() == 2){
            if((hxpUserecord.getBackOneUser() == null || hxpUserecord.getBackTwoUser() == null)){
                throw new ServiceException("归还该化学品需要双人验证，请先完成验证！");
            }
        }

        if(hxpUserecord.getBackOneUser() == null){
            hxpUserecord.setBackOneUser(SecurityUtils.getUserId());
        }

        hxpUserecord.setUpdateTime(DateUtils.getNowDate());
        hxpUserecord.setUpdateBy(SecurityUtils.getUsername());
        hxpUserecord.setReturnTime(DateUtils.getNowDate());
        hxpUserecord.setUseStatus(0);
        hxpUserecordMapper.updateHxpUserecord(hxpUserecord);

        // 归还成功 修改 库存剩余量
        hxpStock.setOutUsages(hxpUserecord.getReturnStockNum());
        hxpStock.setUpdateTime(DateUtils.getNowDate());
        hxpStock.setUpdateBy(SecurityUtils.getUsername());
        hxpStockMapper.updateHxpStock(hxpStock);

        // 归还自动处理超时未归还报警
        hxpAlarmRecordMapper.updateByReturnUserecord(hxpUserecord.getId());

        if(hxpUserecord.getLockLogId() != null){
            HxpCabinetlockLog hxpCabinetlockLog = new HxpCabinetlockLog();
            hxpCabinetlockLog.setId(hxpUserecord.getLockLogId());
            hxpCabinetlockLog.setUserecordId(hxpUserecord.getId());
            hxpCabinetlockLogMapper.updateHxpCabinetlockLog(hxpCabinetlockLog);
        }

        return hxpUserecord;
    }

    /**
     * 批量删除化学品使用记录
     *
     * @param ids 需要删除的化学品使用记录主键
     * @return 结果
     */
    @Override
    public int deleteHxpUserecordByIds(Long[] ids) {
        return hxpUserecordMapper.deleteHxpUserecordByIds(ids);
    }

    /**
     * 删除化学品使用记录信息
     *
     * @param id 化学品使用记录主键
     * @return 结果
     */
    @Override
    public int deleteHxpUserecordById(Long id) {
        return hxpUserecordMapper.deleteHxpUserecordById(id);
    }

    @Override
    public List<AioUserecordVo> queryRecordList(AioUserecordVo aioUserecordVo) {
        return hxpUserecordMapper.queryRecordList(aioUserecordVo);
    }

    @Override
    public AioUserValidationVo userValidation(AioUserValidationVo userValidationVo) {

        // 查询用户信息
        logger.info("双卡验证，用户卡号：" + userValidationVo.getCardNum());
//        String cardNum = Long.toHexString(Long.parseLong(userValidationVo.getCardNum())).toUpperCase();

        String cardNum = userValidationVo.getCardNum();

        R<SysUser> user = remoteUserService.getUserInfoByCardNum(cardNum, SecurityConstants.INNER);

        if (R.FAIL == user.getCode()) {
            throw new ServiceException(user.getMsg());
        }
        if (StringUtils.isNull(user) || StringUtils.isNull(user.getData())) {
            throw new ServiceException("刷卡用户不存在！");
        }

        // 查询用户信息之后还有确认身份权限  -待功能完成后补充
        SysUser sysUser = user.getData();
        // 判断是否是实验室安全责任人
        int count = hxpUserecordMapper.selectIsAdminOrSafeUser(userValidationVo.getSubId(), sysUser.getUserId());
        if(count > 0){

        }/*else if(){
            // TODO 判断是否有申请门禁开锁
        }*/
        else {
            throw new ServiceException("您当前无权限验证，请联系管理员！");
        }

        userValidationVo.setUserId(sysUser.getUserId());
        userValidationVo.setNickName(sysUser.getNickName());
        userValidationVo.setPhonenumber(sysUser.getPhonenumber());
        userValidationVo.setPosition(sysUser.getPosition());
        userValidationVo.setPositionName(sysUser.getPositionName());

        return userValidationVo;
    }

    @Override
    public boolean selectIsAdminOrSafeUser(Long subId, Long userId) {
        if(hxpUserecordMapper.selectIsAdminOrSafeUser(subId, userId) > 0){
            return true;
        }
        return false;
    }

    @Override
    public AioUserValidationVo faceAuth(AioSubInfoVo aioSubInfoVo) {
        Map<String,Object> subInfo = hxpUserecordMapper.selectSubInfoById(aioSubInfoVo.getSubId());
        if(subInfo == null){
            throw new ServiceException("该实验室暂无管理员，请先配置！");
        }

        Long userId = null;
        FaceCompare faceCompare = new FaceCompare();
        faceCompare.setData(aioSubInfoVo.getData());

        Long adminId = Long.parseLong(Optional.ofNullable(String.valueOf(subInfo.get("adminId"))).orElse(""));
        if(adminId != null){
            faceCompare.setUserId(adminId);
            R r= remoteFaceService.compare(faceCompare);
            if(HttpStatus.SUCCESS == r.getCode()){
                userId = adminId;
            }
        }
        if(userId == null){
            String safeUserIds = (String) subInfo.get("safeUserId");
            if(safeUserIds != null){
                String[] ids = safeUserIds.split(",");
                for (int i = 0; i < ids.length; i++) {
                    if(StringUtils.isNotBlank(ids[i])){
                        faceCompare.setUserId(Long.parseLong(ids[i]));
                        R r = remoteFaceService.compare(faceCompare);
                        if(HttpStatus.SUCCESS == r.getCode()){
                            userId = Long.parseLong(ids[i]);
                            break;
                        }
                    }
                }
            }
        }

        if(userId == null){
            throw new ServiceException("您当前没有验证权限，请联系管理员！");
        }

        R<SysUser> user = remoteUserService.getUserInfoByUserId(userId, SecurityConstants.INNER);

        if (R.FAIL == user.getCode()) {
            throw new ServiceException(user.getMsg());
        }
        if (StringUtils.isNull(user) || StringUtils.isNull(user.getData())) {
            throw new ServiceException("验证失败，用户不存在！");
        }
        SysUser sysUser = user.getData();

        AioUserValidationVo userValidationVo = new AioUserValidationVo();
        userValidationVo.setUserId(sysUser.getUserId());
        userValidationVo.setNickName(sysUser.getNickName());
        userValidationVo.setPhonenumber(sysUser.getPhonenumber());
        userValidationVo.setPosition(sysUser.getPosition());
        userValidationVo.setPositionName(sysUser.getPositionName());

        return userValidationVo;
    }

    /**
     * 检测领用超时
     */
    @Override
    public void checkOvertime() {
        List<HxpUserecord> hxpUserecordList = hxpUserecordMapper.selectByOvertime();

        // 系统通知 未领用即携带化学品离开实验室-实验室安全责任人
        Map<String, Object> msgData = new HashMap<>();
        msgData.put("sendRange", 3);
        msgData.put("messClass", -1);
        msgData.put("content", "系统检测到：您当前有化学品领用超时未归还，请您确认！");

        List<Long> recordIds = new ArrayList<>();
        Map<String, Object> userMsg;

        List<Map<String, Object>> userMsgList = new ArrayList<>();
        Map<Long, String> subMsg = new HashMap<>();
        for (HxpUserecord a : hxpUserecordList) {
            recordIds.add(a.getId());
            userMsg = new HashMap<>();
            userMsg.put("joinUserId", a.getUserId());
            userMsg.put("isRead", false);
            userMsgList.add(userMsg);
            msgData.put("messageUserList", userMsgList);

            subMsg.put(a.getSubId(), subMsg.get(a.getSubId()) == null ? "" : "，" + a.getChemicalName());

            // 领用超时报警记录
            HxpAlarmRecord hxpAlarmRecord = new HxpAlarmRecord();

            Map<String,Object> subInfo = hxpUserecordMapper.selectSubInfoById(a.getSubId());

            hxpAlarmRecord.setAlarmContent(subInfo.get("name") + "：化学品" + a.getChemicalName() + "领用超时未归还，请尽快确认处理。");
            hxpAlarmRecord.setAlarmType(1);
            hxpAlarmRecord.setHasValid(1);
            hxpAlarmRecord.setAlarmMode(1);
            hxpAlarmRecord.setAlarmTime(DateUtils.getNowDate());
            hxpAlarmRecord.setSubId(a.getSubId());
            hxpAlarmRecord.setUserecordId(a.getId());
            hxpAlarmRecord.setHandlingStatus(1);
            hxpAlarmRecord.setLiableUserIds(a.getUserId() + "");

            hxpAlarmRecordMapper.insertHxpAlarmRecord(hxpAlarmRecord);
        }
        if(recordIds.size() > 0){
            hxpUserecordMapper.updateUserecordOvertimeByIds(recordIds);
        }

        if(userMsgList.size() > 0){
            // 领用超时进行通知
            remoteMessageContentService.addDynamicMessage(msgData);
        }

        subMsg.forEach((k,v) -> {
            Map<String, Object> subMsgData = new HashMap<>();
            subMsgData.put("sendRange", 3);
            subMsgData.put("messClass", -1);
            subMsgData.put("content", v + "化学品超过领用时长未归还，请您确认！");

            Map<String,Object> subInfo = hxpUserecordMapper.selectSubInfoById(k);
            String safeUserId = "";
            if(subInfo != null){
                // 通知实验室安全责任人
                safeUserId = Optional.ofNullable(subInfo.get("safeUserId")).toString();
                if(org.apache.commons.lang3.StringUtils.isNotBlank(safeUserId)){
                    String[] userIds = safeUserId.split(",");
                    Map<String, Object> msg;
                    List<Map<String, Object>> msgList = new ArrayList<>();
                    for (String userId : userIds) {
                        msg = new HashMap<>();
                        msg.put("joinUserId", userId);
                        msg.put("isRead", false);
                        msgList.add(msg);
                    }
                    subMsgData.put("messageUserList", msgList);

                    remoteMessageContentService.addDynamicMessage(subMsgData);
                }
            }
        });
    }

    @Override
    public HxpUserecordDetailVo queryDetailById(Long id) {
        HxpUserecordDetailVo userecordDetail = hxpUserecordMapper.queryDetailById(id);

        return userecordDetail;
    }
}
