package tech.glinfo.enbao.modules.mq;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tech.glinfo.enbao.common.contants.AppContants;
import tech.glinfo.enbao.common.utils.*;
import tech.glinfo.enbao.modules.service.BaiduApiService;
import tech.glinfo.enbao.modules.sh.entity.*;
import tech.glinfo.enbao.modules.sh.form.ProtocolContent;
import tech.glinfo.enbao.modules.sh.service.OtherShDeviceRecordService;
import tech.glinfo.enbao.modules.sh.service.OtherShDeviceService;
import tech.glinfo.enbao.modules.sh.service.OtherShDlinkService;
import tech.glinfo.enbao.modules.sh.service.ShDevicePasswordService;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//人脸智能锁
@Component("faceLockParse")
public class FaceLockParse implements IParse {

    private final static Logger logger = LoggerFactory.getLogger(FaceLockParse.class);

    @Autowired
    private OtherShDeviceService otherShDeviceService;

    @Autowired
    private OtherShDeviceRecordService otherShDeviceRecordService;

    @Autowired
    private ShDevicePasswordService shDevicePasswordService;

    @Autowired
    private OtherShDlinkService otherShDlinkService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private MqProducer mqProducer;

    @Autowired
    private TimeParseUtils timeParseUtils;

    @Autowired
    private BaiduApiService baiduApiService;

    @Override
    public Map<String, String> run(Object o, Map<String, String> datas) {
        ShDeviceEntity device = (ShDeviceEntity) o;
        Map<String, String> ws = new HashMap<>();

//        ws.put("deviceId", String.valueOf(device.getId()));
        final String receiveId = datas.get("receiveId");

        new Thread(() -> {
            //检测有没待下发指令
            String send = redisUtils.get("device:sendcmd:" + receiveId);
            if(send != null) {
                mqProducer.sendT(send);
            }

            ShDeviceEntity deviceEntity = new ShDeviceEntity();
            deviceEntity.setId(device.getId());
            deviceEntity.setOnlineStatus(2);
            deviceEntity.setOnlineTime(new Date());
            otherShDeviceService.updateById(deviceEntity);
        }).start();

        if("91".equals(datas.get("cmd"))) {//登录包
            redisUtils.delete(receiveId);
        }else if("92".equals(datas.get("cmd"))&& "00".equals(datas.get("content").substring(0, 2))) {//登录包
            //下发使用期限成功删除
            redisUtils.delete("device:sendcmd:" + receiveId);
        }
        else if("08".equals(datas.get("cmd"))) {//登录包

            redisUtils.set(datas.get("mac").toUpperCase(), datas.toString(), 180);//3分钟有效

            //校验设备时钟
            new Thread(new Runnable() {
                @Override
                public void run() {
                    logger.info("start checkDeviceTime");
                    timeParseUtils.checkDeviceTime1(receiveId, datas.get("content"), "11");
                }
            }).start();

            return datas;
        }else if("01".equals(datas.get("cmd"))) {//数据上报
            //数据上报
            //查询解析指令集
            List<ShInstructionParsingEntity> cmds = otherShDeviceService.getDeviceInstructionList(device.getProductId(), datas.get("cmd"));
            if (cmds != null && cmds.size() > 0) {
                int length = 0;
                //解析设备报文内容
                String content1 = datas.get("content");
                Map<String, Object> map = new HashMap<>();
                for (ShInstructionParsingEntity cmd : cmds) {
                    String hex = content1.substring(length, length + cmd.getLength());
                    String hex1 = String.valueOf(Integer.valueOf(hex, 16));
                    map.put(cmd.getName(), hex1);
                    ws.put(cmd.getName(), hex1);
                    length += cmd.getLength();
                }
                otherShDeviceService.updateDeviceData(JSON.toJSONString(map), device.getId());
            }

        } else if("1F".equals(datas.get("cmd"))) {//远程开锁请求
            redisUtils.set(receiveId +":open", 1, 60);//30S有效
            ws.put("open", "1");

        } else if("1D".equals(datas.get("cmd")) && "01".equals(datas.get("content").substring(0, 2))) {//查询动态密码/临时密码
            //临时密码
            int count = shDevicePasswordService.count(new QueryWrapper<ShDevicePasswordEntity>().eq("device_id", device.getId()).eq("status", 1));
            ProtocolContent protocol = new ProtocolContent();
            protocol.setCmd("1D");
            protocol.setDeviceType("11");
            protocol.setReceiveId(device.getNumbering());
            if (count > 0) {
                ShDevicePasswordEntity passwordEntity = shDevicePasswordService.getOne(new QueryWrapper<ShDevicePasswordEntity>().eq("device_id", device.getId()).eq("status", 1).last("LIMIT 1"));
                StringBuilder sb = new StringBuilder();
                sb.append(ByteUtils.int2Hex(count));
                sb.append("01");
                sb.append("FF");
                Date date;
                if (passwordEntity.getExpiredTime() != null) {
                    date = passwordEntity.getExpiredTime();
                }else {
                    date = DateUtils.addDateMinutes(new Date(), 5);
                }
                sb.append(ByteUtils.int2Hex((int) (date.getTime() / 1000)));
                sb.append("00");
                if (passwordEntity.getType() == 1) {
                    sb.append(ByteUtils.int2Hex(8));
                }else {
                    sb.append(ByteUtils.int2Hex(6));
                }
                sb.append(ByteUtils.strToHex(passwordEntity.getPassword()));
                sb.append(passwordEntity.getType() == 1 ? "" : "00");
                protocol.setContent(sb.toString());
                logger.debug("存lockpwd=" + device.getId());
                redisUtils.set("lockpwd" + device.getId(), passwordEntity.getId(), 60);
                if (passwordEntity.getExpiredTime() == null) {
                    passwordEntity.setExpiredTime(date);
                    shDevicePasswordService.updateById(passwordEntity);
                }

            }else {
                protocol.setContent("0000000000000000000000000000000000");
            }
            //下发给MQ，IoT接收到MQ消息会下发给设备
            mqProducer.sendT(JSON.toJSONString(protocol));
        }else if("1D".equals(datas.get("cmd")) && "02".equals(datas.get("content").substring(0, 2))) {
            String content = datas.get("content");
            String id = redisUtils.get("lockpwd" + device.getId());
            logger.debug("取lockpwd=" + device.getId());
            if (id != null) {
                ShDevicePasswordEntity one = shDevicePasswordService.getById(id);
                one.setId(Integer.parseInt(id));
                String s = content.substring(2, 4);
//                int sta = Integer.parseInt(content.substring(0, 2), 16);
                if (s.equals("00")) {
                    one.setStatus(4);
                }else {
                    one.setStatus(2);
                    ws.put("dpwd", one.getPassword());
                }
                shDevicePasswordService.updateById(one);
                redisUtils.delete("lockpwd" + device.getId());
            }

        }else if("00".equals(datas.get("cmd"))) {
            String content = datas.get("content");//图片base64
            String type = datas.get("imgType");//0x00:未知 0x01:门铃抓拍 0X02:远程开锁抓拍 0x03:比对抓拍
            if("03".equals(type)) {//人脸比对
                long start = System.currentTimeMillis();
                String tips = null;
                //人脸比对
                JSONObject res = baiduApiService.search(content, "facelock"+device.getId());//组名：facelock+设备ID
                boolean check = false;
                if(res != null && res.get("result") != null && !"null".equals(res.get("result").toString())) {
                    JSONObject result = res.getJSONObject("result");
                    JSONArray userList = result.getJSONArray("user_list");
                    if(userList.length() > 0) {
                        check = true;
                        JSONObject object = userList.getJSONObject(0);
                        logger.info("检索回来人员：{}", object.toString(2));
                        //假设检索成功，发送开锁指令
                        mqProducer.sendCmd("23", receiveId, "11", "01000000");
                    }
                }
                if(!check) {//失败
                    logger.info("人脸比对失败，找不到人脸信息");
                    tips = "人脸比对失败";
                    mqProducer.sendCmd("23", receiveId, "11", "02000000");
                } else {
                    tips = "人脸比对成功";
                }
                logger.info("接收到图片比对完成花费：{}", System.currentTimeMillis()-start);
                ws.put("tips", DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss") + " " + tips);
            } else {
                ws.put("img", content);
                redisUtils.set(AppContants.DEVICE_OPEN_EVENT + device.getNumbering(), 1, 60);
            }
        }else if("84".equals(datas.get("cmd"))) {//使用期限返回
            String content = datas.get("content");
            if (content.startsWith("FFFF")) {
                ws.put("serviceLife", "永久使用");
            }else {
                String hex = content.substring(0, 4);
                String year = String.valueOf(Integer.valueOf(hex, 16));
                String hex1 = content.substring(4, 6);
                String month = StringUtils.appendString(String.valueOf(Integer.valueOf(hex1, 16)), 2, true, "0");
                String hex2 = content.substring(6, 8);
                String day = StringUtils.appendString(String.valueOf(Integer.valueOf(hex2, 16)), 2, true, "0");
                String hex3 = content.substring(8, 10);
                String hour = StringUtils.appendString(String.valueOf(Integer.valueOf(hex3, 16)), 2, true, "0");
                String hex4 = content.substring(10, 12);
                String minute = StringUtils.appendString(String.valueOf(Integer.valueOf(hex4, 16)), 2, true, "0");
                String hex5 = content.substring(12, 14);
                String second = StringUtils.appendString(String.valueOf(Integer.valueOf(hex5, 16)), 2, true, "0");
                String date = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
                System.out.println("serviceLife : " + date);
                ws.put("serviceLife", date);
            }

        }else if("83".equals(datas.get("cmd"))) {//读取设备时间返回
            String content = datas.get("content");
            String hex = content.substring(0, 4);
            String year = String.valueOf(Integer.valueOf(hex, 16));
            String hex1 = content.substring(4, 6);
            String month = StringUtils.appendString(String.valueOf(Integer.valueOf(hex1, 16)), 2, true, "0");
            String hex2 = content.substring(6, 8);
            String day = StringUtils.appendString(String.valueOf(Integer.valueOf(hex2, 16)), 2, true, "0");
            String hex3 = content.substring(8, 10);
            String hour = StringUtils.appendString(String.valueOf(Integer.valueOf(hex3, 16)), 2, true, "0");
            String hex4 = content.substring(10, 12);
            String minute = StringUtils.appendString(String.valueOf(Integer.valueOf(hex4, 16)), 2, true, "0");
            String hex5 = content.substring(12, 14);
            String second = StringUtils.appendString(String.valueOf(Integer.valueOf(hex5, 16)), 2, true, "0");
            String date = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
            System.out.println("serviceLife : " + date);
            ws.put("time", date);
        }else if("20".equals(datas.get("cmd"))) {
            String content = datas.get("content");
            logger.debug("事件上报 : {}", content);
            /*int action = Integer.parseInt(content.substring(8, 10), 16);
            int ID = Integer.parseInt(content.substring(10, 12), 16);
            ShDeviceRecordEntity recordEntity = new ShDeviceRecordEntity();
            recordEntity.setDeviceId(device.getId());
            recordEntity.setAction(action);
            recordEntity.setRemark(String.valueOf(ID));
            otherShDeviceRecordService.save(recordEntity);*/
//            611E1444
//            030400000035141E61

            String type = content.substring(0, 2);
            String code = content.substring(2, 4);
            String time = content.substring(10, 18);
            String tips = null;
            switch (type) {
                case "01"://开锁事件
                    if (!"00".equals(code) && !"FE".equals(code)) {
                        tips = OpenEnventEnum.getName(code);
                        ShDeviceRecordEntity recordEntity = new ShDeviceRecordEntity();
                        recordEntity.setDeviceId(device.getId());
                        recordEntity.setAction(Integer.parseInt(code, 16));
                        recordEntity.setRemark(tips);
                        otherShDeviceRecordService.save(recordEntity);

                        //下发场景
                        sendCmd(device.getId());
                    }
                    break;
                case "02" :
                    tips = TipsEnventEnum.getName(code);
                    break;
                case "03":
                    tips = ErrorEnventEnum.getName(code);
                    break;
                case "04":
                    tips = "远程请求开锁";
                    break;
                default:
                    break;
            }
            logger.warn("门锁事件：{}", tips);
            if(tips != null) {
                ws.put("tips", DateUtils.stampToTime(Long.valueOf(time, 16) * 1000) + " " + tips);
                ws.put("type", type);
            }

        }/*else if("23".equals(datas.get("cmd")) && "00".equals(datas.get("content"))) {//@TODO 暂时留着
            sendCmd(device.getId());
        }*/
        return ws;
    }

    private void sendCmd(Integer id) {
        String sss = DateUtils.format(new Date(), "yyyy-MM-dd HH:mm");
        ShDlinkEntity dlinkEntity = otherShDlinkService.checkTime(sss.substring(sss.length()-5), id);
        if (dlinkEntity != null) {
            String key = "device:dlink:" + dlinkEntity.getStart() + "-" + dlinkEntity.getEnd() + ":" + dlinkEntity.getDeviceId();
            String json = redisUtils.get(key);
            logger.info("场景找到1" + json);
            if (StringUtils.isNotBlank(json)) {
                for (String s : json.split("-")) {
                    logger.info("场景找到2" + s);
                    mqProducer.sendT(s);
                }
            }
        }
    }
}
