package com.ruoyi.app.service.impl;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.ruoyi.app.DTO.HookBindBatchListDTO;
import com.ruoyi.app.DTO.HookBindDetailDTO;
import com.ruoyi.app.domain.*;
import com.ruoyi.app.domain.request.EditHookBindBatch;
import com.ruoyi.app.domain.request.ReqHookBind;
import com.ruoyi.app.domain.request.ReqHookBindList;
import com.ruoyi.app.domain.request.ReqHookRegister;
import com.ruoyi.app.mapper.*;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import org.bouncycastle.cert.ocsp.Req;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.app.service.IHookBindService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;

import static com.ruoyi.common.utils.uuid.IdUtils.fastSimpleUUID;

/**
 * 吊钩绑定Service业务层处理
 * 
 * @author coede
 * @date 2025-03-19
 */
@Service
public class HookBindServiceImpl implements IHookBindService 
{
    @Autowired
    private HookBindMapper hookBindMapper;

    @Autowired
    private NFIDReadRecordMapper NFIDReadRecordMapper;

    @Autowired
    private RedisCache redisCache;

    //待删

//    @Autowired
//    private DistributeBatchMapper distributeBatchMapper;
//
//    @Autowired
//    private HookRegisterMapper hookRegisterMapper;
//
//    @Autowired
//    private EntranceBatchMapper entranceBatchMapper;
//
//    @PostConstruct
//    private void buildData(){
//        List<DistributeBatch> distributeBatches = distributeBatchMapper.selectDistributeBatchList(new DistributeBatch());
//
//        List<HookRegister> hookRegisters = hookRegisterMapper.selectHookRegisterList(new ReqHookRegister());
//
//        for(DistributeBatch item : distributeBatches){
//            String batchNo = fastSimpleUUID();
//            EntranceBatch entranceBatch = entranceBatchMapper.selectEntranceBatchById(item.getEntranceBatchId());
//            Date bindTime = getRandomTimeBetween10PMAnd3AM(entranceBatch.getEntranceTime());
//            List<HookBind> hookBindArr = new ArrayList<>();
//            for (int i = 0; i < item.getAmount(); i++) {
//                HookBind hookBind = new HookBind();
//                hookBind.setBatchNo(batchNo);
//                hookBind.setHookNo(findHookRegister(hookRegisters).getHookNo());
//                hookBind.setBindTime(bindTime);
//                hookBind.setDistributeBatchId(item.getId());
//                hookBind.setSlaughterCode(item.getSlaughterCode());
//                hookBind.setCreateTime(bindTime);
//                hookBind.setCreateBy(item.getCreateBy());
//                hookBindArr.add(hookBind);
//            }
//            hookBindMapper.insertHookBindBatch(hookBindArr);
//        }
//    }
//    private static Date getRandomTimeBetween10PMAnd3AM(Date inputDate) {
//        Random random = new Random();
//
//        // 将Date转换为LocalDateTime以便操作
//        LocalDateTime date = inputDate.toInstant()
//                .atZone(ZoneId.systemDefault())
//                .toLocalDateTime();
//
//        // 当天晚上10点 (22:00)
//        LocalDateTime start = date.toLocalDate().atTime(22, 0);
//
//        // 次日凌晨3点 (03:00)
//        LocalDateTime end = date.toLocalDate().plusDays(1).atTime(3, 0);
//
//        // 计算两个时间点之间的秒数差
//        long startSeconds = start.atZone(ZoneId.systemDefault()).toEpochSecond();
//        long endSeconds = end.atZone(ZoneId.systemDefault()).toEpochSecond();
//
//        // 生成随机秒数偏移量
//        long randomSeconds = startSeconds + (long)(random.nextDouble() * (endSeconds - startSeconds));
//
//        // 转换为Date
//        return Date.from(Instant.ofEpochSecond(randomSeconds)
//                .atZone(ZoneId.systemDefault())
//                .toInstant());
//    }
//    private HookRegister findHookRegister(List<HookRegister> list){
//        int index = new Random().nextInt(list.size());
//        return list.get(index);
//    }
    //

    /**
     * 查询吊钩绑定
     * 
     * @param batchNo 批次号
     * @return 吊钩绑定
     */
    @Override
    public HookBindBatchListDTO selectHookBindByBatch(String batchNo)
    {

        return hookBindMapper.selectHookBindByBatch(batchNo);
    }
    /**
     * 查询吊钩绑定详情-修改等场景使用所以不需要缓存
     *
     * @param hookNo 吊钩号号
     * @return 吊钩绑定
     */
    @Override
    public HookBindDetailDTO selectHookBindOnlyDetail(String hookNo)
    {
        ReqHookBind req = new ReqHookBind();
        req.setHookNo(hookNo);
        List<HookBindDetailDTO> res = hookBindMapper.selectHookBindDetail(req);
        if (res != null && res.size() > 0){
            return res.get(0);
        }else {
            return new HookBindDetailDTO();
        }
    }

    /**
     * 查询吊钩绑定详情-白条称重使用，需要缓存切数据有时间期限判断
     *
     * @param hookNo 吊钩号号
     * @return 吊钩绑定
     */
    @Override
    public HookBindDetailDTO selectHookBindDetail(String hookNo)
    {
        HookBindDetailDTO cache = redisCache.getCacheObject(getCacheKey(hookNo));
        if (StringUtils.isNotNull(cache))
        {
            return cache;
        }
        ReqHookBind req = new ReqHookBind();
        req.setHookNo(hookNo);
        List<HookBindDetailDTO> res = hookBindMapper.selectHookBindDetail(req);
        if (res != null && res.size() > 0){
            //12个小时过期
            redisCache.setCacheObject(getCacheKey(hookNo), res.get(0), 12*60, TimeUnit.MINUTES);
            return res.get(0);
        }else {
            return new HookBindDetailDTO();
        }
    }

    /**
     * 查询吊钩绑定列表
     * 
     * @param hookBind 吊钩绑定
     * @return 吊钩绑定
     */
    @Override
    public List<HookBind> selectHookBindList(HookBind hookBind)
    {
        return hookBindMapper.selectHookBindList(hookBind);
    }

    /**
     * 按批次查询吊钩绑定列表
     *
     * @param req 吊钩绑定
     * @return 吊钩绑定
     */
    @Override
    public List<HookBindBatchListDTO> selectHookBindListByBatch(ReqHookBindList req)
    {
        return hookBindMapper.selectHookBindListByBatch(req);
    }

    /**
     * 校验相同时间吊钩是否已绑定
     *
     * @param hookBind 吊钩绑定
     * @return 结果
     */
    @Override
    public HookBind checkHookNoUnique(HookBind hookBind)
    {
        return hookBindMapper.checkHookNoUnique(hookBind);

    }

    /**
     * 新增吊钩绑定
     * 
     * @param hookBind 吊钩绑定
     * @return 结果
     */
    @Override
    public int insertHookBind(HookBind hookBind)
    {
        hookBind.setCreateTime(DateUtils.getNowDate());
        return hookBindMapper.insertHookBind(hookBind);
    }

    /**
     * 新增吊钩批量绑定
     *
     * @param batch 吊钩绑定
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertHookBindBatch(List<HookBind> batch,String [] hookNos)
    {
        //将绑定的吊钩识别记录设置为已绑定
        setBindRecord(hookNos);

        int row = hookBindMapper.insertHookBindBatch(batch);
        if (row > 0)
        {
            ReqHookBind detailReq = new ReqHookBind();
            detailReq.setBatchNo(batch.get(0).getBatchNo());
            List<HookBindDetailDTO> res = hookBindMapper.selectHookBindDetail(detailReq);
            if (res != null){
                for (HookBindDetailDTO hookBindDetailDTO : res) {
                    redisCache.deleteObject(getCacheKey(hookBindDetailDTO.getHookNo()));
                    redisCache.setCacheObject(getCacheKey(hookBindDetailDTO.getHookNo()), hookBindDetailDTO,60 * 60, TimeUnit.SECONDS);
//                    redisCache.expire(getCacheKey(hookBindDetailDTO.getHookNo()), 60 * 60);//一小时过期
                }
            }

        }
        return row;
    }

    /**
     * 修改吊钩绑定
     * 
     * @param hookBind 吊钩绑定
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateHookBind(HookBind hookBind)
    {
        hookBind.setUpdateTime(DateUtils.getNowDate());
        if(hookBind.getSlaughterCode() !=null){
            hookBind.setBindTime(DateUtils.getNowDate());
        }
        ReqHookBind req = new ReqHookBind();
        req.setId(hookBind.getId());
        List<HookBindDetailDTO> res = hookBindMapper.selectHookBindDetail(req);
        if (res != null && res.size() > 0){
            HookBindDetailDTO temp = res.get(0);
            if (!StringUtils.equals(temp.getHookNo(), hookBind.getHookNo()))
            {
                //缓存的键被改了
                redisCache.deleteObject(getCacheKey(temp.getHookNo()));
            }
        }
        int row = hookBindMapper.updateHookBind(hookBind);
        if (row > 0)
        {
            redisCache.setCacheObject(getCacheKey(hookBind.getHookNo()), hookBind,60 * 60, TimeUnit.SECONDS);
            //redisCache.expire(getCacheKey(hookBind.getHookNo()), 60 * 60);//一小时过期
        }
        return row;
    }

    /**
     * 批量修改吊钩绑定
     *
     * @param req 吊钩绑定
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateHookBindBatch(EditHookBindBatch req)
    {
        req.setUpdateTime(DateUtils.getNowDate());
        //生成新对象
        List<HookBind> hookBindArr = new ArrayList<>();

        for(String hook : req.getHookNoListArr()){
            HookBind hookBind = new HookBind();
            hookBind.setBatchNo(req.getBatchNo());
            hookBind.setHookNo(hook);
            hookBind.setBindTime(req.getBindTime());
            hookBind.setDistributeBatchId(req.getDistributeBatchId());
            hookBind.setSlaughterCode(req.getSlaughterCode());
            hookBind.setCreateTime(DateUtils.getNowDate());
            hookBind.setCreateBy(req.getUpdateBy());
            hookBind.setUpdateTime(DateUtils.getNowDate());
            hookBind.setUpdateBy(req.getUpdateBy());
            //未传绑定时间默认当前时间
            if(req.getBindTime() == null){
                hookBind.setBindTime(DateUtils.getNowDate());
            }else{
                hookBind.setBindTime(req.getBindTime());
            }
            hookBindArr.add(hookBind);
        }
        String[] oldHookNos = hookBindMapper.selectHookNoByBatchNo(req.getBatchNo());
        //1.把使用的识别记录设为未使用
        setUnBindRecord(oldHookNos);
        //2.删除旧记录
        hookBindMapper.deleteHookBindById(req.getBatchNo());
        //3.把新的记录设置为已使用
        setBindRecord(req.getHookNoListArr());
        //4.重新创建记录
        int row = hookBindMapper.insertHookBindBatch(hookBindArr);
        //int row = hookBindMapper.updateHookBindBatch(req);
        //修改后的添加到缓存中
        if (row > 0)
        {
            ReqHookBind detailReq = new ReqHookBind();
            detailReq.setBatchNo(req.getBatchNo());
            List<HookBindDetailDTO> res = hookBindMapper.selectHookBindDetail(detailReq);
            if (res != null){
                for (HookBindDetailDTO hookBindDetailDTO : res) {
                    redisCache.deleteObject(getCacheKey(hookBindDetailDTO.getHookNo()));
                    redisCache.setCacheObject(getCacheKey(hookBindDetailDTO.getHookNo()), hookBindDetailDTO,60 * 60, TimeUnit.SECONDS);
                  //  redisCache.expire(getCacheKey(hookBindDetailDTO.getHookNo()), 60 * 60);//一小时过期
                }
            }

        }
        return row;
    }

    /**
     * 批量删除吊钩绑定
     * 
     * @param batchNos 需要删除的吊钩绑定主键批次编号集合
     * @return 结果
     */
    @Override
    public int deleteHookBindByIds(String[] batchNos)
    {
        return hookBindMapper.deleteHookBindByIds(batchNos);
    }

    /**
     * 删除吊钩绑定信息
     * 
     * @param batchNo 吊钩绑定批次编号
     * @return 结果
     */
    @Override
    public int deleteHookBindById(String batchNo)
    {
        return hookBindMapper.deleteHookBindById(batchNo);
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey)
    {
        return CacheConstants.APP_HOOK_BIND + configKey;
    }

    /**
     * 设置识别记录为已使用
     *
     * @param hookNos 吊钩号
     * @return 结果
     */
    private void setBindRecord(String[] hookNos) throws RuntimeException
    {
        //将绑定的吊钩识别记录设置为已绑定
        int updated =  NFIDReadRecordMapper.setBindByHook(hookNos);
        //并发情况判断
        if (updated < hookNos.length) {
            throw new RuntimeException("吊钩记录已被使用");
        }
    }

    /**
     * 设置识别记录为已使用
     *
     * @param hookNos 吊钩号
     * @return 结果
     */
    private void setUnBindRecord(String[] hookNos) throws RuntimeException
    {
        //将绑定的吊钩识别记录设置为已绑定
        int updated =  NFIDReadRecordMapper.setUnBindByHook(hookNos);
        //并发情况判断
        if (updated < hookNos.length) {
            throw new RuntimeException("吊钩记录已被使用");
        }
    }

    /**
     * 清除绑定关系
     *
     * @return 结果
     */
    @Override
    public int cleanHookBind()
    {
        return hookBindMapper.cleanHookBind();
    }

}
