package com.ruoyi.common.server;


import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.utils.ModBusUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;


/**
 * @Project : huimv.shiwan
 * @Package : com.huimv.biosafety.uface.controller
 * @Description : TODO
 * @Version : 1.0
 * @Author : ZhuoNing
 * @Create : 2020-12-25
 **/
@ChannelHandler.Sharable
@Component
public class EnvInputServerHandler extends ChannelInboundHandlerAdapter {
    private static final Logger log = LoggerFactory.getLogger(EnvInputServerHandler.class);
    private StringBuilder askTextSb = null;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;


    private Map<String, String> channelMap = new ConcurrentHashMap<>();

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 当客户端连接时，打印出客户端的 IP 地址
        System.out.println("连接成功");
        ByteBuf bufff = Unpooled.buffer();
        bufff.writeBytes(hexString2Bytes("5A000101000000DCE5"));
        ctx.writeAndFlush(bufff);
        super.channelActive(ctx);
    }

    // 设备数据的前缀
    private static final String DEVICE_PREFIX = "device:";
    private  static Integer INDEX = 1;
    //
    public void appendClientAsk(String text) {
        if (this.askTextSb == null) {
            askTextSb = new StringBuilder();
        }
        askTextSb.append(text);
    }
    @Override
    public  void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        ByteBuf byteBuf = (ByteBuf) msg;
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);
        String str = ModBusUtils.bytes2HexString(bytes);
        System.out.println("收到的数据："+str);
        if (!str.startsWith("5A 00")){
            System.out.println("数据错误:"+str);
            return;
        }

        if (bytes.length >80 &&  bytes.length<90){
            int startIndex = 9;
            int length = 20;
            char[] asciiChars = new char[length];
            for (int i = startIndex; i <  startIndex + length; i++) {
                asciiChars[i - startIndex] = (char) (bytes[i] & 0xFF); // 使用 & 0xFF 来确保正确处理可能的负值
            }
            String asciiString = new String(asciiChars);
            // 输出结果
            System.out.println("ASCII String: " + asciiString);
            String key = ctx.channel().id().asLongText();
            channelMap.put(key,asciiString);
            return;
        }

        //Netty需要用ByteBuf传输
        ByteBuf bufff = Unpooled.buffer();
        if (bytes.length < 20 &&bytes.length > 9 ){
            bufff.writeBytes(hexString2Bytes("5A0001021000080000000"+INDEX+"01020006ED08"));
            INDEX++;
            if (INDEX > 4){
                INDEX =1;
            }
        }
        ctx.writeAndFlush(bufff);
        String mapKey = ctx.channel().id().asLongText();
        String clientip = channelMap.get(mapKey);
        System.out.println(clientip + "-clientip");
        if(bytes.length   > 49){
            Date now = new Date();
            String[] s = str.split(" ");
            StringBuilder epc = new StringBuilder();
            for (int i = 9; i < 9 + Integer.parseInt(s[8], 16); i++) {
                epc.append(s[i]);
            }
            //String tian = s[23];
            String key = DEVICE_PREFIX + epc;
            System.out.println(epc + "-epc");
            long timeDifferenceMillis ;
            if (redisTemplate.hasKey(key)) {
                String storedTimestampStr = redisTemplate.opsForValue().get(key);
                if (storedTimestampStr != null) {
                    long storedTimeMillis = Long.parseLong(storedTimestampStr);
                    // 计算时间差（毫秒）
                     timeDifferenceMillis = System.currentTimeMillis() - storedTimeMillis;
                    //小于一分钟，更新时间戳
                    if (timeDifferenceMillis < 60 * 1000) {
                        redisTemplate.opsForValue().set(key, String.valueOf(System.currentTimeMillis()));
                        redisTemplate.expire(key,6,TimeUnit.HOURS);
                        System.out.println("时间小于一分钟，更新时间戳");
                        return;
                    }else {
                        redisTemplate.delete(key);
                    }
                } else {
                    // 如果键不存在，可以抛出一个异常或者返回一个特定的值
                    throw new RuntimeException("Timestamp key not found in Redis");
                }

            } else {

                System.out.println("存储");
                return;
            }


            }


        //停止读卡
//        bufff.writeBytes(hexString2Bytes("5A000102FF0000885A"));
//        ctx.writeAndFlush(bufff);

        super.channelRead(ctx, msg);
    }

    public   static boolean isStartOfToday(Date date) {
        // 创建一个示例的LocalDateTime对象
        LocalDateTime exampleTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        // 获取今天的开始时间
        LocalDateTime todayStart = LocalDateTime.of(LocalDateTime.now().toLocalDate(), LocalTime.MIDNIGHT);

        // 比较给定的时间和今天的开始时间
        if (exampleTime.isAfter(todayStart)) {
            System.out.println("给定的时间大于今天的开始时间");
            return true;
        } else {
            System.out.println("给定的时间不大于今天的开始时间");
            return false;
        }
    }
    public  boolean isTimeBetween(LocalTime startTime, LocalTime endTime) {
        LocalDateTime now = LocalDateTime.now();

        // 获取当前日期的00:00和23:59:59
        LocalDateTime startOfDay = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime endOfDay = startOfDay.plusDays(1).minusSeconds(1);

        // 创建表示时间段的开始和结束时间的LocalDateTime对象
        LocalDateTime startDateTime = LocalDateTime.of(now.toLocalDate(), startTime);
        LocalDateTime endDateTime = LocalDateTime.of(now.toLocalDate(), endTime);

        // 判断当前时间是否在两个时间段之一内
        if (endDateTime.isBefore(startDateTime)) {
            // 时间段跨越午夜，分两部分判断
            return (now.isAfter(startDateTime) && now.isBefore(endOfDay)) ||
                    (now.isAfter(startOfDay) && now.isBefore(endDateTime));
        } else {
            // 时间段在同一天内，直接判断
            return now.isAfter(startDateTime) && now.isBefore(endDateTime);
        }
    }
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        String key = channel.id().asLongText(); // 或者使用其他唯一标识符
        System.out.println("退出-->"+key);
        channelMap.remove(key);
        super.channelInactive(ctx);
    }
    public static byte[] hexString2Bytes(String src) {

        int l = src.length() / 2;

        byte[] ret = new byte[l];

        for (int i = 0; i < l; i++) {

            ret[i] = (byte) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();

        }

        return ret;

    }





    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

//        if (true){
//            ctx.writeAndFlush(Unpooled.copiedBuffer(new byte[]{1, 2, 3}));
//        }

//        if (askTextSb.toString().indexOf("end") != -1) {
//            // {处理客户端消息}


//            handleClientAskCmd(askTextSb.toString(), ctx);
//            //清空重置;
//            askTextSb.delete(0, askTextSb.length());
//        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        if (cause.getMessage().indexOf("Connection reset") != -1) {
            log.info("相关采集器设备正在重启:" + cause.toString());
        }
        ctx.close();
    }

    //应答
    public void answerCmd(String answerText, ChannelHandlerContext ctx) {
        ctx.writeAndFlush(Unpooled.copiedBuffer(answerText.getBytes()));
    }


}
