package com.yanzhu.manage.service.impl;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.common.utils.MD5Utils;
import com.yanzhu.common.core.constant.CacheConstants;
import com.yanzhu.common.core.constant.SecurityConstants;
import com.yanzhu.common.core.utils.StringUtils;
import com.yanzhu.common.redis.service.RedisService;
import com.yanzhu.manage.domain.AttendanceCfg;
import com.yanzhu.manage.domain.AttendanceUbiDevice;
import com.yanzhu.manage.domain.ProProjectInfoSubdeptsUsers;
import com.yanzhu.manage.mapper.AttendanceCfgMapper;
import com.yanzhu.manage.mapper.AttendanceUbiDeviceMapper;
import com.yanzhu.manage.mapper.ProProjectInfoSubdeptsUsersMapper;
import com.yanzhu.manage.service.IUniService;
import com.yanzhu.manage.utils.UniUtils;
import com.yanzhu.system.api.RemoteUserService;
import com.yanzhu.system.api.domain.SysUser;
import okhttp3.Request;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class UniServiceImpl implements IUniService{

    @Autowired
    private RedisService redisService;

    @Autowired
    private AttendanceCfgMapper attendanceCfgMapper;

    @Autowired
    private RemoteUserService remoteUserService;

    @Autowired
    private AttendanceUbiDeviceMapper attendanceUbiDeviceMapper;

    @Autowired
    private ProProjectInfoSubdeptsUsersMapper proProjectInfoSubdeptsUsersMapper;
    private void clearAuthCache(long projectId){
        String cacheKey=CacheConstants.UNI_AUTH+projectId;
        redisService.deleteObject(cacheKey);
    }

    @Override
    public Map<String,String> auth(long projectId) {
        String cacheKey=CacheConstants.UNI_AUTH+projectId;
        Map<String,String>  authMap = redisService.getCacheObject(cacheKey);
        String authInfo="404";
        String projectGuid="404";
        if(authMap!=null){
            return authMap;
        }else{
            authMap=new HashMap<>();
        }
        AttendanceCfg where=new AttendanceCfg();
        where.setProjectId(projectId);
        List<AttendanceCfg> list=attendanceCfgMapper.selectAttendanceCfgList(where);
        if(list.size()>0){
            AttendanceCfg cfg=list.get(0);
            if(cfg.getVendorsCode().equals("uni") && StringUtils.isNotEmpty(cfg.getVendorsParameter())){
                JSONObject json=JSON.parseObject(cfg.getVendorsParameter());
                String appKey=json.getString("AppKey");
                String appSecret=json.getString("AppSecret");
                projectGuid=json.getString("projectGuid");
                String timestamp=""+new Date().getTime();
                Map<String, String> headerParams=new HashMap<>();
                headerParams.put("appKey",appKey);
                headerParams.put("timestamp",timestamp);
                String sign=appKey+timestamp+appSecret;
                headerParams.put("sign", UniUtils.md5(sign).toLowerCase());
                Request request = new Request.Builder()
                        .url(UniUtils.getAuthUrl(projectGuid))
                        .get().headers(UniUtils.setHeaderParams(headerParams))
                        .build();
                String str=UniUtils.getResult(request);
                JSONObject jo=JSON.parseObject(str);
                String data= jo.getString("data");
                if(StringUtils.isNotEmpty(data)){
                    authInfo=data;
                    authMap.put("token",authInfo);
                    authMap.put("projectGuid",projectGuid);
                    redisService.setCacheObject(cacheKey, authMap, 20l, TimeUnit.HOURS);//缓存20小时
                }
            }
        }
        return authMap;
    }

    @Override
    public String admitCreate(JSONObject data) {
        long projectId=data.getLong("projectId");
        data.remove("projectId");
        Request request=new Request.Builder()
                .url(UniUtils.ADMITCREATE)
                .post(UniUtils.toJsonBody(data))
                .headers(UniUtils.setHeaderParams(auth(projectId)))
                .build();
        String res=UniUtils.getResult(request);
        JSONObject jo=JSON.parseObject(res);
        if(jo.getLong("result").intValue()==1){
            return jo.getJSONObject("data").getString("admitGuid");
        }
        if("token is illegal".equals(jo.getString("msg"))){
            clearAuthCache(projectId);
            return admitCreate(data);
        }
        return null;
    }

    @Override
    public String admitUpdate(JSONObject data) {
        long projectId=data.getLong("projectId");
        data.remove("projectId");
        Request request=new Request.Builder()
                .url(UniUtils.ADMITUPDATE)
                .post(UniUtils.toJsonBody(data))
                .headers(UniUtils.setHeaderParams(auth(projectId)))
                .build();
        String res=UniUtils.getResult(request);
        JSONObject jo=JSON.parseObject(res);
        if("token is illegal".equals(jo.getString("msg"))){
            clearAuthCache(projectId);
            return admitUpdate(data);
        }

        return  jo.getString("msg");
    }

    @Override
    public boolean admitDeletee(JSONObject data) {
        long projectId=data.getLong("projectId");
        data.remove("projectId");
        Request request=new Request.Builder()
                .url(UniUtils.ADMITDELETE)
                .post(UniUtils.toJsonBody(data))
                .headers(UniUtils.setHeaderParams(auth(projectId)))
                .build();
        String res=UniUtils.getResult(request);
        JSONObject jo=JSON.parseObject(res);
        if("token is illegal".equals(jo.getString("msg"))){
            clearAuthCache(projectId);
            return admitDeletee(data);
        }
        return  jo.getLong("result").intValue()==1;
    }

    @Override
    public JSONObject admitDetail(JSONObject data) {
        return null;
    }

    @Override
    public JSONObject admitPage(JSONObject data) {
        return null;
    }

    @Override
    public JSONObject faceRegister(JSONObject data) {
        long projectId=data.getLong("projectId");
        data.remove("projectId");
        Request request=new Request.Builder()
                .url(UniUtils.FACEREGISTER)
                .post(UniUtils.toJsonBody(data))
                .headers(UniUtils.setHeaderParams(auth(projectId)))
                .build();
        String res=UniUtils.getResult(request);
        JSONObject jo=JSON.parseObject(res);
       if(jo.getLong("result").intValue()==1){
           return  jo.getJSONObject("data");
       }
        if("token is illegal".equals(jo.getString("msg"))){
            clearAuthCache(projectId);
            return faceRegister(data);
        }
       return  null;
    }

    @Override
    public boolean faceDelete(JSONObject data) {
        long projectId=data.getLong("projectId");
        data.remove("projectId");
        Request request=new Request.Builder()
                .url(UniUtils.FACEDELETE)
                .post(UniUtils.toJsonBody(data))
                .headers(UniUtils.setHeaderParams(auth(projectId)))
                .build();
        String res=UniUtils.getResult(request);
        JSONObject jo=JSON.parseObject(res);
        if("token is illegal".equals(jo.getString("msg"))){
            clearAuthCache(projectId);
            return faceDelete(data);
        }
        return  jo.getLong("result").intValue()==1;
    }

    @Override
    public JSONObject faceDetail(JSONObject data) {
        return null;
    }

    @Override
    public String deviceCreate(JSONObject data) {
        long projectId=data.getLong("projectId");
        Request request=new Request.Builder()
                .url(UniUtils.DEVICECREATE)
                .post(UniUtils.toJsonBody(data))
                .headers(UniUtils.setHeaderParams(auth(projectId)))
                .build();
        String res=UniUtils.getResult(request);
        JSONObject jo=JSON.parseObject(res);
        if(jo.getLong("result").intValue()==1){
            return "success";
        }
        if("token is illegal".equals(jo.getString("msg"))){
            clearAuthCache(projectId);
            return deviceCreate(data);
        }
        return jo.getString("msg");
    }

    @Override
    public JSONObject deviceUpdate(JSONObject data) {
        return null;
    }

    @Override
    public JSONObject deviceDelete(JSONObject data) {
        long projectId=data.getLong("projectId");
        Request request=new Request.Builder()
                .url(UniUtils.DEVICEDELETE)
                .post(UniUtils.toJsonBody(data))
                .headers(UniUtils.setHeaderParams(auth(projectId)))
                .build();
        String res=UniUtils.getResult(request);
        JSONObject jo=JSON.parseObject(res);
        if(jo.getLong("result").intValue()==1){
            return jo.getJSONObject("data");
        }
        if("token is illegal".equals(jo.getString("msg"))){
            clearAuthCache(projectId);
            return deviceDelete(data);
        }
        return null;
    }

    @Override
    public JSONObject deviceDetail(JSONObject data) {
        long projectId=data.getLong("projectId");
        Request request=new Request.Builder()
                .url(UniUtils.DEVICEDETAIL)
                .post(UniUtils.toJsonBody(data))
                .headers(UniUtils.setHeaderParams(auth(projectId)))
                .build();
        String res=UniUtils.getResult(request);
        JSONObject jo=JSON.parseObject(res);
        if(jo.getLong("result").intValue()==1){
            return jo.getJSONObject("data");
        }
        if("token is illegal".equals(jo.getString("msg"))){
            clearAuthCache(projectId);
            return deviceDetail(data);
        }
        return null;
    }

    @Override
    public String authDevice(JSONObject data) {
        long projectId=data.getLong("projectId");
        Request request=new Request.Builder()
                .url(UniUtils.AUTHDEVICE)
                .post(UniUtils.toJsonBody(data))
                .headers(UniUtils.setHeaderParams(auth(projectId)))
                .build();
        String res=UniUtils.getResult(request);
        JSONObject jo=JSON.parseObject(res);
        if(jo.getLong("result").intValue()==1){
            return "success";
        }
        if("token is illegal".equals(jo.getString("msg"))){
            clearAuthCache(projectId);
            return deviceCreate(data);
        }
        return jo.getString("msg");
    }

    @Override
    public JSONObject authDeviceUpdate(JSONObject data) {
        return null;
    }

    @Override
    public String authDeviceRevoke(JSONObject data) {
        long projectId=data.getLong("projectId");
        Request request=new Request.Builder()
                .url(UniUtils.AUTHDEVICEREVOKE)
                .post(UniUtils.toJsonBody(data))
                .headers(UniUtils.setHeaderParams(auth(projectId)))
                .build();
        String res=UniUtils.getResult(request);
        JSONObject jo=JSON.parseObject(res);
        if(jo.getLong("result").intValue()==1){
            return "success";
        }
        if("token is illegal".equals(jo.getString("msg"))){
            clearAuthCache(projectId);
            return authDeviceRevoke(data);
        }
        return jo.getString("msg");
    }
    @Override
    public Long syncUniDeviceUser(Long deviceId,Long projectId){
       AttendanceUbiDevice device=attendanceUbiDeviceMapper.selectAttendanceUbiDeviceById(deviceId);
       ProProjectInfoSubdeptsUsers userWhere=new ProProjectInfoSubdeptsUsers();
       userWhere.setProjectId(projectId);
       List<ProProjectInfoSubdeptsUsers> userList=proProjectInfoSubdeptsUsersMapper.selectProProjectInfoSubdeptsUsersList(userWhere);
       JSONObject jo=new JSONObject();
       jo.put("projectId",projectId);
       jo.put("deviceNo",device.getDeviceNo());
       List<String> admitGuidList=new ArrayList<>();
       for(ProProjectInfoSubdeptsUsers u :userList){
           String admitGuid=u.getAdmitGuid();
           if(StringUtils.isNotEmpty(admitGuid)){
               admitGuidList.add(admitGuid);
           }
       }
       for(int i=0;i<admitGuidList.size();i+=50){
           String admitGuids="";
           for(int j=0;j<50 && j+i<admitGuidList.size();j++){
               admitGuids+=admitGuidList.get((i+j))+",";
           }
           if(admitGuids.length()>0){
               admitGuids=admitGuids.substring(0,admitGuids.length()-1);
           }
           jo.put("admitGuids",admitGuids);
           authDevice(jo);
       }
       return 1l;
    }

    /**
     * 同步删除设备 1.删除设备人员关系 2.删除设备
     * @param ids
     * @return
     */
    @Override
    public long syncUniDeviceDelete(Long[] ids) {
        long cnt=0;
        for(Long id :ids){
            cnt+=deleteDevice(id);
        }
        return cnt;
    }

    /**
     * 用户设备销权识别主体
     * @param id
     */
    @Override
    public void syncUserRevoke(Long id) {
        ProProjectInfoSubdeptsUsers user= proProjectInfoSubdeptsUsersMapper.selectProProjectInfoSubdeptsUsersById(id);
        if(user==null){
            return;
        }
        AttendanceUbiDevice where=new AttendanceUbiDevice();
        where.setProjectId(user.getProjectId());
        List<AttendanceUbiDevice> devList=attendanceUbiDeviceMapper.selectAttendanceUbiDeviceList(where);
        for(AttendanceUbiDevice device :devList){
            JSONObject jo=new JSONObject();
            jo.put("projectId",user.getProjectId());
            jo.put("deviceNo",device.getDeviceNo());
            jo.put("admitGuids",user.getAdmitGuid());
            authDeviceRevoke(jo);
        }
    }

    /**
     * 用户设备授权识别主体
     * @param id
     */
    @Override
    public void syncUserAuthDevice(Long id) {
        ProProjectInfoSubdeptsUsers user= proProjectInfoSubdeptsUsersMapper.selectProProjectInfoSubdeptsUsersById(id);
        if(user==null){
            return;
        }
        AttendanceUbiDevice where=new AttendanceUbiDevice();
        where.setProjectId(user.getProjectId());
        List<AttendanceUbiDevice> devList=attendanceUbiDeviceMapper.selectAttendanceUbiDeviceList(where);
        for(AttendanceUbiDevice device :devList) {
            JSONObject jo=new JSONObject();
            jo.put("projectId",user.getProjectId());
            jo.put("deviceNo",device.getDeviceNo());
            jo.put("admitGuids",user.getAdmitGuid());
            authDevice(jo);
        }
    }

    private Long deleteDevice(Long id) {
        AttendanceUbiDevice device=attendanceUbiDeviceMapper.selectAttendanceUbiDeviceById(id);
        if(device==null){
            return 0l;
        }
        Long projectId=device.getProjectId();
        ProProjectInfoSubdeptsUsers userWhere=new ProProjectInfoSubdeptsUsers();
        userWhere.setProjectId(projectId);
        List<ProProjectInfoSubdeptsUsers> userList=proProjectInfoSubdeptsUsersMapper.selectProProjectInfoSubdeptsUsersList(userWhere);
        JSONObject jo=new JSONObject();
        jo.put("projectId",projectId);
        jo.put("deviceNo",device.getDeviceNo());
        jo.put("source",device.getSource());
        List<String> admitGuidList=new ArrayList<>();
        for(ProProjectInfoSubdeptsUsers u :userList){
            String admitGuid=u.getAdmitGuid();
            if(StringUtils.isNotEmpty(admitGuid)){
                admitGuidList.add(admitGuid);
            }
        }
        for(int i=0;i<admitGuidList.size();i+=50){
            String admitGuids="";
            for(int j=0;j<50 && j+i<admitGuidList.size();j++){
                admitGuids+=admitGuidList.get((i+j))+",";
            }
            if(admitGuids.length()>0){
                admitGuids=admitGuids.substring(0,admitGuids.length()-1);
            }
            jo.put("admitGuids",admitGuids);
            authDeviceRevoke(jo);
        }

        deviceDelete(jo);
        return 1l;
    }

    @Override
    public Long syncUniDevice(Long deviceId,Long projectId){
        AttendanceUbiDevice device=attendanceUbiDeviceMapper.selectAttendanceUbiDeviceById(deviceId);
        if(device!=null){
            JSONObject jo=new JSONObject();
            jo.put("projectId",projectId);
            jo.put("name",device.getName());
            jo.put("tag",device.getTag());
            jo.put("source",device.getSource());
            jo.put("sceneGuid","");
            jo.put("deviceNo",device.getDeviceNo());
            jo.put("addition","{'recType':'1'}");
            String ret= deviceCreate(jo);
            if("success".equals(ret)||"device is occupied".equals(ret)){
                JSONObject joDetail=deviceDetail(jo);
                device.setHasRegister(1l);
                device.setLastActiveTime(new Date());
                device.setDeviceModel(joDetail.getString("deviceModel"));
                device.setDeviceState(joDetail.getLong("state"));
                device.setOnlineState(joDetail.getLong("onlineState"));
                device.setVersionNo(joDetail.getString("versionNo"));
                device.setAddition(joDetail.getString("addition"));
                device.setRecType(joDetail.getLong("recType"));
                attendanceUbiDeviceMapper.updateAttendanceUbiDevice(device);
                return  1l;
            }
        }
        return 0l;
    }
    @Override
    public Long syncUniUser(Long userId, Long projectId) {
        SysUser user=remoteUserService.getSysUserInfo(userId, SecurityConstants.INNER).getData();
        JSONObject jo=JSON.parseObject(user.getUserInfos());
        String admitGuid=jo.getString("admitGuid");
        String faceGuid=jo.getString("faceGuid");
        JSONObject userJo=new JSONObject();
        userJo.put("projectId",projectId);
        userJo.put("name",user.getUserName());
        userJo.put("phone",user.getPhonenumber());
        userJo.put("tag",user.getNickName());
        userJo.put("cardNo",user.getUserId()+","+projectId);
        userJo.put("idCardNo",user.getCardCode());
        userJo.put("password","");
        userJo.put("addition","");
        boolean hasUpdate=false;
        if(StringUtils.isEmpty(admitGuid)){
            //未注册人员
            admitGuid=admitCreate(userJo);
            user.setAdmitGuid(admitGuid);
            jo.put("admitGuid",admitGuid);
            hasUpdate=true;
        }else{
            //已注册
            userJo.put("admitGuid",admitGuid);
            String upMsg= admitUpdate(userJo);
            if("admit not exist".equals(upMsg)){
               userJo.remove("admitGuid");
                userJo.put("projectId",projectId);
                admitGuid=admitCreate(userJo);
                jo.put("admitGuid",admitGuid);
                hasUpdate=true;
            }
        }
        JSONObject faceJo=new JSONObject();
        faceJo.put("projectId",projectId);
        faceJo.put("base64","");
        faceJo.put("admitGuid",admitGuid);
        faceJo.put("url",user.getUserPicture());
        //faceJo.put("url","https://uniubi-aiot.oss-cn-hangzhou.aliyuncs.com/detect/20241007/211204-71D9BCBE526C4F57B8D31ECAE03AEBFB");
        faceJo.put("faceTag","");
        HttpServletRequest request =((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
        String url= request.getRemoteAddr();
        if(StringUtils.isNotEmpty(faceGuid)){
            JSONObject faceDel=new JSONObject();
            faceDel.put("projectId",projectId);
            faceDel.put("admitGuid",admitGuid);
            faceDel.put("faceGuid",faceGuid);
           faceDelete(faceDel);
        }
       //注册图像
       JSONObject faceRes= faceRegister(faceJo);
       if(faceRes!=null) {
           jo.put("faceGuid", faceRes.getString("faceGuid"));
           jo.put("uniFaceInfo", faceRes.toJSONString());
           hasUpdate=true;
       }
       user.setUserInfos(jo.toJSONString());
       if(hasUpdate){
         Long ret=  remoteUserService.updateUserInfo(user,SecurityConstants.INNER).getData();
         if(ret==null){
             return 0l;
         }
         return ret.longValue();
       }

       return 0l;
    }

}
