package com.jsowell.netty.handler.yunkuaichong;

import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.google.common.primitives.Bytes;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.domain.ykc.LoginRequestData;
import com.jsowell.common.core.domain.ykc.YKCDataProtocol;
import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode;
import com.jsowell.common.util.BytesUtil;
import com.jsowell.common.util.StringUtils;
import com.jsowell.common.util.YKCUtils;
import com.jsowell.netty.factory.YKCOperateFactory;
import com.jsowell.pile.domain.PileBasicInfo;
import com.jsowell.pile.domain.ykcCommond.IssueQRCodeCommand;
import com.jsowell.pile.domain.ykcCommond.ProofreadTimeCommand;
import com.jsowell.pile.service.PileBasicInfoService;
import com.jsowell.pile.service.PileMsgRecordService;
import com.jsowell.pile.service.YKCPushCommandService;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Component
public class LoginRequestHandler extends AbstractHandler {
    private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.LOGIN_CODE.getBytes());

    @Autowired
    private PileBasicInfoService pileBasicInfoService;

    @Autowired
    private YKCPushCommandService ykcPushCommandService;

    @Autowired
    private PileMsgRecordService pileMsgRecordService;

    private List<String> newProgramVersionList = Lists.newArrayList("c6-30");

    @Override
    public void afterPropertiesSet() throws Exception {
        YKCOperateFactory.register(type, this);
    }

    public static void main(String[] args) {
        String msg = "8800000000009000020f56312e323035303000898604940121c138531304";
        byte[] msgBody = BytesUtil.str2Bcd(msg);

        int startIndex = 0;
        int length = 7;

        // 桩编码
        byte[] pileSnByte = BytesUtil.copyBytes(msgBody, startIndex, length);
        String pileSn = BytesUtil.binary(pileSnByte, 16);
        // log.info("桩号：{}", pileSn);

        // 桩类型  0 表示直流桩， 1 表示交流桩
        startIndex += length;
        length = 1;
        byte[] pileTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String pileType = BytesUtil.bcd2Str(pileTypeByteArr);

        // 充电枪数量
        startIndex += length;
        byte[] connectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String connectorNum = BytesUtil.bcd2Str(connectorNumByteArr);

        // 通信协议版本  版本号乘 10，v1.0 表示 0x0A
        startIndex += length;
        byte[] communicationVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        // int i = Integer.parseInt(BytesUtil.bcd2Str(communicationVersionByteArr)); // 0F --> 15
        BigDecimal bigDecimal = new BigDecimal(BytesUtil.bcd2Str(communicationVersionByteArr));
        BigDecimal communicationVersionTemp = bigDecimal.divide(new BigDecimal(10));
        String communicationVersion = "v" + communicationVersionTemp;

        // 程序版本
        startIndex += length;
        length = 8;
        byte[] programVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String programVersion = BytesUtil.ascii2Str(programVersionByteArr);
        log.info("程序版本:{}  length:{}", programVersion, programVersion.length());

        // 网络连接类型  0x00 SIM 卡  0x01 LAN   0x02 WAN  0x03 其他
        startIndex += length;
        length = 1;
        byte[] internetConnectionTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String internetConnection = BytesUtil.bcd2Str(internetConnectionTypeByteArr);

        // sim卡
        startIndex += length;
        length = 10;
        byte[] simCardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String iccid = BytesUtil.bin2HexStr(simCardNumByteArr);

        // 运营商  0x00 移动  0x02 电信  0x03 联通  0x04 其他
        startIndex += length;
        length = 1;
        byte[] businessTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String business = BytesUtil.bcd2Str(businessTypeByteArr);
    }

    @Override
    public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, Channel channel) {
        // 获取消息体
        byte[] msgBody = ykcDataProtocol.getMsgBody();

        int startIndex = 0;
        int length = 7;

        // 桩编码
        byte[] pileSnByte = BytesUtil.copyBytes(msgBody, startIndex, length);
        String pileSn = BytesUtil.binary(pileSnByte, 16);

        // 保存时间
        saveLastTimeAndCheckChannel(pileSn, channel);

        // 桩类型  0 表示直流桩， 1 表示交流桩
        startIndex += length;
        length = 1;
        byte[] pileTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String pileType = BytesUtil.bcd2Str(pileTypeByteArr);

        // 充电枪数量
        startIndex += length;
        byte[] connectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String connectorNum = BytesUtil.bcd2Str(connectorNumByteArr);

        // 通信协议版本  版本号乘 10，v1.0 表示 0x0A
        startIndex += length;
        byte[] communicationVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        BigDecimal bigDecimal = new BigDecimal(BytesUtil.bcd2Str(communicationVersionByteArr));
        BigDecimal communicationVersionTemp = bigDecimal.divide(new BigDecimal(10));
        String communicationVersion = "v" + communicationVersionTemp;

        // 程序版本
        startIndex += length;
        length = 8;
        byte[] programVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String programVersion = BytesUtil.ascii2Str(programVersionByteArr);
        // log.info("程序版本:{}  length:{}", programVersion, programVersion.length());

        // 网络连接类型  0x00 SIM 卡  0x01 LAN   0x02 WAN  0x03 其他
        startIndex += length;
        length = 1;
        byte[] internetConnectionTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String internetConnection = BytesUtil.bcd2Str(internetConnectionTypeByteArr);

        // sim卡
        startIndex += length;
        length = 10;
        byte[] simCardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String iccid = BytesUtil.bin2HexStr(simCardNumByteArr);

        // 运营商  0x00 移动  0x02 电信  0x03 联通  0x04 其他
        startIndex += length;
        length = 1;
        byte[] businessTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String business = BytesUtil.bcd2Str(businessTypeByteArr);

        // *********************** 字段解析完成，下面进行逻辑处理 *********************** //
        if (verifyTheDuplicateRequest(ykcDataProtocol, channel)) {
            return null;
        }

        LoginRequestData loginRequestData = LoginRequestData.builder()
                .pileSn(pileSn)
                .pileType(pileType)
                .connectorNum(connectorNum)
                .communicationVersion(communicationVersion)
                .programVersion(programVersion)
                .internetConnection(internetConnection)
                .iccid(iccid)
                .business(business)
                .build();

        // 结果（默认 0x01:登录失败）
        byte[] flag = Constants.oneByteArray;

        // 通过桩编码SN查询数据库，如果有数据，则登录成功，否则登录失败
        PileBasicInfo pileBasicInfo = null;
        try {
            pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn);
        } catch (Exception e) {
            log.error("selectPileBasicInfoBySN发生异常", e);
        }

        if (pileBasicInfo != null) {
            flag = Constants.zeroByteArray;

            // 异步修改充电桩状态
            CompletableFuture.runAsync(() -> {
                try {
                    // 更改桩和该桩下的枪口状态分别为 在线、空闲 公共方法修改状态
                    pileBasicInfoService.updateStatus(BytesUtil.bcd2Str(ykcDataProtocol.getFrameType()), pileSn, null, null, null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });

            // 异步发送对时指令
            CompletableFuture.runAsync(() -> {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 对时
                ProofreadTimeCommand command = ProofreadTimeCommand.builder().pileSn(pileSn).build();
                ykcPushCommandService.pushProofreadTimeCommand(command);
            });

            // log.info("下面进行下发二维码 pileSn:{}, thread:{}", pileSn, Thread.currentThread().getName());
            // 异步发送下发二维码指令
            CompletableFuture.runAsync(() -> {
                try {
                    Thread.sleep(600);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 下发二维码
                IssueQRCodeCommand issueQRCodeCommand = IssueQRCodeCommand.builder().pileSn(pileSn).build();
                ykcPushCommandService.pushIssueQRCodeCommand(issueQRCodeCommand);
            });

            if (StringUtils.equals("00", internetConnection)) {
                CompletableFuture.runAsync(() -> {
                    // 充电桩使用的sim卡，把信息存库
                    try {
                        pileBasicInfoService.updatePileSimInfo(pileSn, iccid);
                        // pileBasicInfoService.updatePileSimInfoV2(pileSn, iccid);
                    } catch (Exception e) {
                        log.error("更新充电桩sim卡信息失败pileSn:{}, iccid:{}", pileSn, iccid, e);
                    }
                });
            }
        }

        // 异步保持登录报文
        CompletableFuture.runAsync(() -> {
            // 保存报文 没有登录认证通过还要不要保存报文？
            try {
                String jsonMsg = JSON.toJSONString(loginRequestData);
                pileMsgRecordService.save(pileSn, pileSn, type, jsonMsg, ykcDataProtocol.getHEXString());
            } catch (Exception e) {
                log.error("保存报文失败pileSn:{}", pileSn, e);
            }
        });

        // 消息体
        byte[] messageBody = Bytes.concat(pileSnByte, flag);
        return getResult(ykcDataProtocol, messageBody);
    }
}
