package com.yx.face.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yx.face.boot.config.TaskPoolConfig;
import com.yx.face.boot.restful.RestDTO;
import com.yx.face.boot.restful.ServiceException;
import com.yx.face.boot.uitls.*;
import com.yx.face.dao.*;
import com.yx.face.model.dto.WxInfoDTO;
import com.yx.face.model.entity.*;
import com.yx.face.model.query.QueryUser;
import com.yx.face.model.vo.AdminVO;
import com.yx.face.model.vo.UserInfoVO;
import com.yx.face.netty_client.NettyClient;
import com.yx.face.service.AdminService;
import com.yx.face.service.UserInfoService;
import com.yx.face.service.feign.TBDeviceFaceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.sql.Blob;
import java.util.*;


/**
 * @description: 用户基础信息表(UserInfo)表服务实现类 <br>
 * @author: PWB <br>
 * @since: 1.0 <br>
 * @date: 2021-06-04 14:25:50 <br>
 */
@Slf4j
@Service
public class UserInfoServiceImpl implements UserInfoService {
    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    private UserFaceRecordsDao userFaceRecordsDao;
    @Resource
    private FacePassDao facePassDao;
    @Resource
    private FaceDeviceDao faceDeviceDao;
    @Resource
    private FaceRequestLogDao faceRequestLogDao;
    @Resource
    private FaceTaskDao faceTaskDao;
    //常客
    @Resource
    private UserWhitelistDao userWhitelistdao;
    @Resource
    private UserVisitorListDao userVisitorListDao;
    @Resource
    private UserBlackListDao userBlackListDao;
    @Resource
    private UserInfoFromDao userInfoFromDao;
    @Autowired
    private TaskPoolConfig taskPoolConfig;
    @Autowired
    private NettyClient nettyClient;
    @Autowired
    private AsyncTriggerRetryImpl asyncTriggerRetryImpl;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private AdminService adminService;

    //    @Value("${wx.phone.url}")
    private static final String wxUrl = "http://192.168.99.11:9810/winxin-fyzd/weiXin/getPhone";

    @Override
    public String getWxPhone(WxInfoDTO dto) {

        String sync = OkHttpUtils.builder().url(wxUrl)
                // 有参数的话添加参数，可多个
                .addParam("code", dto.getCode())
                .addParam("signature", dto.getSignature())
                .addParam("rawData", dto.getRawData())
                .addParam("iv", dto.getIv())
                .addParam("encryptedData", dto.getEncryptedData())
                .post(true)
                .sync();
        if (org.apache.commons.lang3.StringUtils.isBlank(sync)) {
            throw new ServiceException("获取登录后的session信息失败");
        }
        JSONObject jsonObject = JSON.parseObject(sync);
        String code = jsonObject.getString("code");
        if ("500".equals(code)) {
            throw new ServiceException("网络异常请重新获取哦~");
        }
        String phone = jsonObject.getString("phone");
        if (org.apache.commons.lang3.StringUtils.isBlank(phone)) {
            throw new ServiceException("网络异常请重新获取哦~");
        }
        String openid = jsonObject.getString("openid");
        if (org.apache.commons.lang3.StringUtils.isBlank(openid)) {
            throw new ServiceException("网络异常请重新获取哦~");
        }
        return phone;
    }

    @Override
    public void confirmFaceNotify(String result) {
        Map<String, Object> map = JsonUtils.toMap(result);
        if (CollectionUtils.isEmpty(map)) {
            return;
        }
        String taskId = map.get("taskId").toString();
        String name = map.get("name").toString();
        String phone = map.get("phone").toString();
        String idNumber = map.get("idNumber").toString();
        if (!StringUtils.hasText(taskId)) {
            return;
        }
        if (!StringUtils.hasText(name)) {
            return;
        }
        if (!StringUtils.hasText(phone)) {
            return;
        }
        if (!StringUtils.hasText(idNumber)) {
            return;
        }
        Date now = new Date();
        UserInfo userInfo = new UserInfo();
        userInfo.setPhone(phone);
        userInfo = userInfoDao.selectOne(userInfo);
        String image = buildImage(map.get("img").toString(), phone);
        //添加至用户基础信息表
        if (userInfo == null) {
            userInfo = new UserInfo();
            userInfo.setUsername(name);
            userInfo.setPhone(phone);
            userInfo.setIdNumber(idNumber);
            userInfo.setRoleId(1);
            userInfo.setAuthId(0);
            userInfo.setAvatar(image);
            userInfo.setUpdateTime(now);
            userInfo.setCreateTime(now);
            userInfoDao.insertSelective(userInfo);
        } else {
            userInfo.setUsername(name);
            userInfo.setPhone(phone);
            userInfo.setAvatar(image);
            userInfo.setIdNumber(idNumber);
            userInfo.setUpdateTime(now);
            userInfoDao.updateByPrimaryKeySelective(userInfo);
        }
        //添加至用户人脸记录表
        UserFaceRecords faceRecords = new UserFaceRecords();
        faceRecords.setTaskId(taskId);
        faceRecords.setUserId(userInfo.getId());
        faceRecords.setPhone(userInfo.getPhone());
        faceRecords.setIdNumber(userInfo.getIdNumber());
        faceRecords.setUsername(name);
        faceRecords.setPhoto(image);
        faceRecords.setToken(map.get("token").toString());
        faceRecords.setCreateTime(now);
        userFaceRecordsDao.insertSelective(faceRecords);
        //将该用户下发至员工通道所有设备
        //查询常客以及访客数据
//        UserWhitelist userWhitelist = userWhitelistdao.getByIdNubmer(idNumber);
//        UserVisitorList userVisitorList = userVisitorListDao.getByIdNubmer(idNumber);
//        Integer type = null;
//        Calendar calendar = Calendar.getInstance();
//        calendar.setTime(now);
//        if (null != userWhitelist) {
//            //常客
//            type = 105;
//            //设置时间1年
//            calendar.add(Calendar.YEAR,1);
//        } else {
//            //访客
//            type = 104;
//            //设置时间15天
//            calendar.add(Calendar.DAY_OF_MONTH,15);
//        }
//        //redisUtil.set("yuangongtongdao","")
//        try {
//            downFaceByTask(userInfo, DateUtils.addMinutes(now, -10), calendar.getTime(), type, taskId, userWhitelist, userVisitorList);
//        } catch (Exception e) {
//            log.info("日志" + e.getMessage());
//            e.printStackTrace();
//            throw new ServiceException("下发失败请重新再试哦~");
//        }


    }


    @Override
    public PageInfo<UserInfoVO> getUsers(RestDTO<QueryUser> dto) {
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        return new PageInfo<>(userInfoDao.getUsersByFacePass(dto.getData()));
    }


    @Override
    public Map<String, Object> doGetFacePass(Integer userId, String taskId) {
        log.info("数据*************； " + userId + "*******************" + taskId);
        String admin = taskId;
        //返回值
        Map<String, Object> map = new HashMap<>(2);
        // 人员类型
        Integer type = 3;
        //时间
        Date now = new Date();
        //
        Date date = null;
        //用户信息
        UserInfo userInfo = userInfoDao.selectByPrimaryKey(userId);
        if (org.apache.commons.lang3.StringUtils.isBlank(userInfo.getPhone())) {
            throw new ServiceException("手机号为空请重新登录哦~");
        }
        if (!StringUtils.hasText(userInfo.getAvatar())) {
            throw new ServiceException("人脸照片不规范请重新认证哦~");
        }
        //校验是否在黑名单
        UserBlackList userBlackList = new UserBlackList();
        userBlackList.setPhone(userInfo.getPhone());
        userBlackList.setAdminId(Integer.valueOf(admin));
        List<UserBlackList> select = userBlackListDao.select(userBlackList);
        if (!select.isEmpty()) {
            throw new ServiceException("禁止下发哦~");
        }
        //常客
        UserWhitelist byPhoneAndId = userWhitelistdao.getByPhoneAndId(userInfo.getPhone(), null, Integer.valueOf(admin));
        //访客
        UserVisitorList userVisitorList = userVisitorListDao.getByPhoneAndId(userInfo.getPhone(), Integer.valueOf(admin));
        //常客
        if (byPhoneAndId != null) {
            type = 2;
            //一年
            date = DateUtils.addYears(now, 1);
        } else {
            //12 小时
            date = DateUtils.addHours(now, 12);
        }
        //人脸下发
        try {
            downFaceByTask(userInfo, DateUtils.addMinutes(now, -10), date, type, taskId, byPhoneAndId, userVisitorList);
        } catch (Exception e) {
            log.info("日志" + e.getMessage());
            e.printStackTrace();
            throw new ServiceException("下发失败请重新再试哦~");
        }
        map.put("status", true);
        map.put("date", date);
        return map;
    }


    /**
     * @param userInfo     用户信息
     * @param startTime    开始时间
     * @param endTime      结束时间
     * @param type         类型
     * @param taskId       id
     * @param byPhoneAndId 访客信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void downFaceByTask(UserInfo userInfo, Date startTime, Date endTime, Integer type, String taskId, UserWhitelist byPhoneAndId, UserVisitorList userVisitorList) throws Exception {
        //获取adminId
        //String admin = taskId.split("-")[0];
        String admin = taskId;
        //获取 adminId下的所有设备
        //List<FaceDevice> snList = faceDeviceDao.getSnList(Integer.parseInt(admin));
        //查询员工通道设备(type=2)
        AdminVO adminVO = adminService.getInfo(Integer.valueOf(admin));
        List<FaceDevice> snList = faceDeviceDao.getByAdminAndType(adminVO);
        Map<String, Object> result;
        //天波人脸服务请求日志表
        FaceRequestLog requestLog;
        Date now = new Date();
        //人脸下发表
        FacePass facePass;
        //唯一id
        Long faceTaskId;
        //人脸清除定时任务
        FaceTask faceTask;
        //信息
        String avatar = "";
        //人脸下发到设备里面
        if (!snList.isEmpty()) {
            //获取图片base64
            avatar = getAvatarBase64(userInfo.getId(), userInfo.getAvatar());
            if (!StringUtils.hasText(avatar)) {
                throw new ServiceException("人脸照片不规范下发失败请重新认证");
            }
            for (FaceDevice device : snList) {
                Map<String, Object> params = Maps.newHashMapWithExpectedSize(3);
                List<Map<String, Object>> data = Lists.newArrayListWithExpectedSize(1);
                Map<String, Object> dataItem = Maps.newHashMapWithExpectedSize(8);
                // 下发参数
                dataItem.put("pin", userInfo.getId());
                dataItem.put("name", userInfo.getUsername());
                dataItem.put("validPeriodStart", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startTime));
                dataItem.put("validPeriodEnd", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endTime));
                dataItem.put("userType", 0);
                dataItem.put("photo", avatar);
                if (type == 2) {
                    dataItem.put("rightno", 105);
                } else if (type == 3) {
                    dataItem.put("rightno", 104);
                }
                dataItem.put("cardid", userInfo.getIdNumber());
                data.add(dataItem);
                params.put("SN", device.getSn());
                params.put("Data", data);
                //天波人脸服务请求日志表
                requestLog = new FaceRequestLog();
                requestLog.setName("下发人脸");
                requestLog.setContext("/downUser");
                requestLog.setParams("");
                requestLog.setStatus(1);
                requestLog.setUsedTime(0L);
                requestLog.setUpdateTime(now);
                requestLog.setCreateTime(now);
                //人脸下发记录表
                faceRequestLogDao.insertSelective(requestLog);
                params.put("taskId", requestLog.getId());
                //人脸下发表
                facePass = new FacePass();
                facePass.setUserId(userInfo.getId());
                facePass.setDeviceSn(device.getSn());
                facePass.setDeviceId(device.getId());
                facePass.setStartTime(startTime);
                facePass.setEndTime(endTime);
                facePass.setAdminId(Integer.valueOf(admin));
                facePass.setStatus(2);
                facePass.setType(type);
                facePass.setTaskId(taskId);
                facePass.setUpdateTime(now);
                facePass.setCreateTime(now);
                //人脸下发
                //添加人脸
                facePassDao.insertSelective(facePass);
                asyncTriggerRetryImpl.send(params, facePass);

                faceTaskId = faceTaskDao.getFaceTaskId(device.getSn(), userInfo.getId());
                faceTask = new FaceTask();
                faceTask.setId(faceTaskId);
                faceTask.setTaskTime(facePass.getEndTime());
                faceTask.setStatus(0);
                faceTask.setUpdateTime(now);
                if (faceTaskId == null) {
                    faceTask.setDeviceSn(device.getSn());
                    faceTask.setUserId(userInfo.getId());
                    faceTask.setCreateTime(now);
                    faceTaskDao.insertSelective(faceTask);
                    continue;
                }
                faceTaskDao.updateByPrimaryKeySelective(faceTask);
            }
        }

        if (byPhoneAndId != null) {
            //更新常客列表
            UserWhitelist userWhitelist = new UserWhitelist();
            userWhitelist.setStatus(1);
            userWhitelist.setUpdateTime(now);
            userWhitelist.setId(byPhoneAndId.getId());
            userWhitelist.setAvatar(userInfo.getAvatar());
            userWhitelist.setIdNumber(userInfo.getIdNumber());
            userWhitelistdao.updateByPrimaryKeySelective(userWhitelist);
            return;
        }
        UserVisitorList userVisitorOne = new UserVisitorList();
        if (userVisitorList == null) {
            //更新游客列表
            userVisitorOne.setAdminId(Integer.valueOf(admin));
            userVisitorOne.setCreateTime(now);
            userVisitorOne.setPhone(userInfo.getPhone());
            userVisitorOne.setAvatar(userInfo.getAvatar());
            userVisitorOne.setIdNumber(userInfo.getIdNumber());
            userVisitorOne.setName(userInfo.getUsername());
            userVisitorListDao.insert(userVisitorOne);
        } else {
            //更新游客列表
            userVisitorOne.setAdminId(Integer.valueOf(admin));
            userVisitorOne.setId(userVisitorList.getId());
            userVisitorOne.setUpdateTime(now);
            userVisitorOne.setAvatar(userInfo.getAvatar());
            userVisitorListDao.updateByPrimaryKeySelective(userVisitorOne);
        }

    }


    /**
     * 根据 userid 或者 图片路径获取 base64 图片
     *
     * @param userId    userinfo id
     * @param avatarUrl 图片路径
     * @return 图片base64
     */
    public String getAvatarBase64(Long userId, String avatarUrl) {
        String avatar = "";
        UserInfoFrom userInfoFrom = userInfoFromDao.selectImgBase(userId);
        if (userInfoFrom != null && userInfoFrom.getImgBase() != null) {
            String encode = Base64Util.encode(userInfoFrom.getImgBase());
            if (StringUtils.hasText(encode)) {
                avatar = encode;
            }
        } else {
            byte[] byteAvatar = Base64Util.getByteArrayFromUrl(avatarUrl);
            if (byteAvatar != null) {
                String encode = Base64Util.encode(byteAvatar);
                if (StringUtils.hasText(encode)) {
                    avatar = encode;
                }
            }
        }
        return avatar;
    }

    private String buildImage(String image, String phone) {
        String path = null;
        if (StringUtils.hasText(image)) {
            String name = phone + UUID.randomUUID().toString().concat(".png");
            path = FileUploadUtil.uploadUtil(image, name);
            return path;
        }
        return path;
    }
}

