package com.community.huiju.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.community.commom.constant.Constant;
import com.community.commom.mode.ResponseBean;
import com.community.commom.uuid.IdGen;
import com.community.commom.hk.HKOpenApi;
import com.community.huiju.dao.*;
import com.community.huiju.exception.WisdomException;
import com.community.huiju.model.*;
import com.community.huiju.service.IHKService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 海康 业务实现
 * @author weiximei
 */
@Service
@Slf4j
public class HKServiceImpl implements IHKService {

    @Autowired
    private TaUserMapper taUserMapper;

    private IdGen idGen = IdGen.get();

    @Autowired
    private TpEquipmentMapper tpEquipmentMapper;

    @Autowired
    private TpConfigurationMapper tpConfigurationMapper;

    @Autowired
    private TpEquipmentTreeMapper tpEquipmentTreeMapper;

    @Autowired
    private TaUserVerifyMapper taUserVerifyMapper;

    /**
     * 获取设备UUID
     * @param equipmentList
     * @return
     */
    private List<Map<String,Object>> getEquipmentUUID(List<TpEquipment> equipmentList) {
        return equipmentList.stream().map(equipment -> {
            TpConfiguration tpConfiguration = tpConfigurationMapper.selectByPrimaryKey(equipment.getUuidId());
            Map<String,Object> map = Maps.newHashMap();
            map.put("doorUuid", tpConfiguration.getDooruuid());
            map.put("deviceUuid", tpConfiguration.getDeviceuuid());
            return map;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean pushPerson(String appUserId, Integer userVerifyId) {
        ResponseBean responseBean = new ResponseBean();
        TaUser user = taUserMapper.selectByPrimaryKey(Integer.parseInt(appUserId));

        TaUserVerify userVerify = taUserVerifyMapper.selectByPrimaryKey(userVerifyId);
        if (null == userVerify) {
            throw new WisdomException("审核数据不存在！");
        }
        TpEquipmentTree tpEquipmentTree = tpEquipmentTreeMapper.selectByCommunityId(userVerify.getCommunityId());

        // 这两个值一般都是同时存在的
        // 当这两个值不存在的时候，就添加海康人员
        if (null == user.getHkUserId() && null == user.getHkPersonNo()) {
            // 设置 海康id
            user.setHkPersonNo(idGen.nextId());
            /**
             * 1.获取部门(比如 住户)
             * 2.根据部门编号推送 海康
             */
            taUserMapper.updateByPrimaryKeySelective(user);
            addUserAndOpenCard(responseBean, user, tpEquipmentTree);
        }


        // 推送海康

        // 给用户添加 海康门禁权限

        List<TpEquipment> tpEquipments = tpEquipmentMapper.selectByCommunityIdAndUnitId(userVerify.getCommunityId(), userVerify.getUnitId(), 4);
        List<Map<String, Object>> equipmentUUID = getEquipmentUUID(tpEquipments);
        StringBuilder doorUuids = new StringBuilder();
        StringBuilder deviceUuids = new StringBuilder();
        equipmentUUID.forEach(e-> {
            doorUuids.append(e.get("doorUuid"));
            doorUuids.append(",");
            deviceUuids.append(e.get("deviceUuid"));
            deviceUuids.append(",");
        });

        Map<String, Object> map = Maps.newHashMap();
        map.put("personIds",String.valueOf(user.getHkUserId()));
        map.put("doorUuids", doorUuids.substring(0, doorUuids.lastIndexOf(",")));
        map.put("secret", tpEquipmentTree.getSecret());
        map.put("appkey", tpEquipmentTree.getAppkey());
        map.put("openapi_ip_port_http", tpEquipmentTree.getHttpServer());
        HKOpenApi.addAuthoritiesByPersonIds(map);

        // 下发门禁权限
        Map<String, Object> downloadAuthorityByPersonIdsMap = Maps.newHashMap();
        downloadAuthorityByPersonIdsMap.put("personIds",String.valueOf(user.getHkUserId()));
        downloadAuthorityByPersonIdsMap.put("doorUuids", doorUuids.substring(0, doorUuids.lastIndexOf(",")));
        downloadAuthorityByPersonIdsMap.put("operateType",1);
        downloadAuthorityByPersonIdsMap.put("includeFinger",1);
        downloadAuthorityByPersonIdsMap.put("secret", tpEquipmentTree.getSecret());
        downloadAuthorityByPersonIdsMap.put("appkey", tpEquipmentTree.getAppkey());
        downloadAuthorityByPersonIdsMap.put("openapi_ip_port_http", tpEquipmentTree.getHttpServer());
        HKOpenApi.downloadAuthorityByPersonIds(downloadAuthorityByPersonIdsMap);

        //--------- 可视对讲 ----------

        Map<String,Object> addOutDoorAuthMap = Maps.newHashMap();
        addOutDoorAuthMap.put("authName", "荟居");
        addOutDoorAuthMap.put("personIds", Arrays.asList(user.getHkUserId()));
        addOutDoorAuthMap.put("secret", tpEquipmentTree.getSecret());
        addOutDoorAuthMap.put("appkey", tpEquipmentTree.getAppkey());

        // 单元门口机
        List<TpEquipment> visualEquipments = tpEquipmentMapper.selectByCommunityIdAndUnitId(userVerify.getCommunityId(), userVerify.getUnitId(), 3);
        List<String> visualList = visualEquipments.stream()
                .map(e-> tpConfigurationMapper.selectByPrimaryKey(e.getUuidId()).getConfigurationValue())
                .collect(Collectors.toList());
//        List<String> visualList = new ArrayList<>();
//        visualList.add("10010100000");
        addOutDoorAuthMap.put("longNums", visualList);
        // 可视对讲下发 权限
        visualIntercomPermissions(addOutDoorAuthMap);
        if ("0".equals(responseBean.getCode())) {
            responseBean.addSuccess("操作成功！");
            return responseBean;
        }
        throw new WisdomException("操作失败!");
    }

    @Override
    @Deprecated
    public ResponseBean downloadAuthorityByDeviceUuids() {
        ResponseBean responseBean = new ResponseBean();
        // 下发门禁权限
        HKOpenApi.downloadAuthorityByDeviceUuids(Maps.newHashMap());
        responseBean.addSuccess("操作成功！");
        return responseBean;
    }

    /**
     * 公共方法
     * 添加人员, 开卡
     *
     * @param response
     * @param user
     */
    private void addUserAndOpenCard(ResponseBean response, TaUser user, TpEquipmentTree tpEquipmentTree) {
        Map<String, Object> parDept = Maps.newHashMap();
        parDept.put("pageNo", 1);
        parDept.put("pageSize", 100);
        parDept.put("deptName", Constant.DEPT_RESIDENTS);
        parDept.put("openapi_ip_port_http", tpEquipmentTree.getHttpServer());
        // 部门UUID
        String deptUuid = getDeptUUID(parDept);

        // 添加人员
        Map<String, Object> parUser = Maps.newHashMap();
        parUser.put("personNo", user.getHkPersonNo());
        parUser.put("personName", user.getUserName());
        parUser.put("phoneNo", user.getLoginName());
        parUser.put("deptUuid", deptUuid);
        parUser.put("secret", tpEquipmentTree.getSecret());
        parUser.put("appkey", tpEquipmentTree.getAppkey());
        parUser.put("openapi_ip_port_http", tpEquipmentTree.getHttpServer());
        Map<String, Object> resultMap = JSONObject.parseObject(HKOpenApi.addUser(parUser), HashMap.class);
        int errorCode = (int) resultMap.get("errorCode");
        if (errorCode == 0) {
            Map<String, Object> resultDataMap = (Map<String, Object>) resultMap.get("data");
            // 开卡 卡号
            long cardNo = System.currentTimeMillis();
            // 海康人员ID
            Integer personId = (Integer) resultDataMap.get("personId");
            TaUser tempUser = taUserMapper.selectByPrimaryKey(user.getId());
            tempUser.setHkUserId(personId);
            tempUser.setHkCardNo(cardNo + "");

            user.setHkUserId(personId);
            // 存储海康人员ID
            int row = taUserMapper.updateByPrimaryKeySelective(tempUser);
            if (row > 0) {
                response.addSuccess("操作成功!");
            } else {
                response.addError("操作失败");
                throw new RuntimeException("数据库添加 家属/租客 人员失败!");
            }

            // 开卡
            List<String> cardAndPersonList = Lists.newArrayList();
            cardAndPersonList.add(cardNo + "," + personId);
            response = openCard(cardAndPersonList, null, tpEquipmentTree);
        } else {
            String errorMessage = String.valueOf(resultMap.get("errorMessage"));
            response.addError(errorMessage);
            log.error("海康添加人员失败! {}", errorMessage);
            throw new RuntimeException(errorMessage);
        }
    }

    /**
     * 批量开卡
     *
     * @param cardIdAndHKUserID list.add("卡号,人员ID")
     * @param expirationTime    有效期为多少? 单位为 年
     * @return
     */
    private ResponseBean openCard(List<String> cardIdAndHKUserID, Integer expirationTime, TpEquipmentTree tpEquipmentTree) {
        ResponseBean response = new ResponseBean();

        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        LocalDate today = LocalDate.now();
        int year = today.getYear();
        // 加上20, 表示加上20年,默认
        if (null == expirationTime || expirationTime <= 0) {
            year += 20;
        } else {
            year += expirationTime;
        }
        int month = today.getMonthValue();
        int day = today.getDayOfMonth();

        Long time = null;
        try {
            time = formatter.parse(year + "-" + month + "-" + day).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }

        // 开卡
        Map<String, Object> parOpenCard = Maps.newHashMap();
        parOpenCard.put("cardAndPerson", cardIdAndHKUserID);
        parOpenCard.put("startTime", System.currentTimeMillis());
        parOpenCard.put("endTime", time);
        parOpenCard.put("secret", tpEquipmentTree.getSecret());
        parOpenCard.put("appkey", tpEquipmentTree.getAppkey());
        parOpenCard.put("openapi_ip_port_http", tpEquipmentTree.getHttpServer());
        JSONObject openCardJSON = JSONObject.parseObject(HKOpenApi.openCard(parOpenCard));
        int code = (int) openCardJSON.get("errorCode");
        if (code == 0) {
            response.addSuccess("操作成功!");
        } else {
            String errorMessage = String.valueOf(openCardJSON.get("errorMessage"));
            response.addError(errorMessage);
            log.error("开卡失败! {}", errorMessage);
            throw new RuntimeException(errorMessage);
        }

        return response;
    }

    /**
     * 获取部门 uuid
     * <p>
     * 这里的部门相当于 小区
     *
     * @return
     */
    private String getDeptUUID(Map<String, Object> parDept) {
        Map<String, Object> deptMap = JSONObject.parseObject(HKOpenApi.getDeptName(parDept), HashMap.class);
        Map<String, Object> deptDataMap = (Map<String, Object>) deptMap.get("data");
        JSONArray jsonArray = (JSONArray) deptDataMap.get("list");
        Map<String, Object> deptListData = (Map<String, Object>) jsonArray.get(0);
        // 部门UUID
        String deptUuid = (String) deptListData.get("deptUuid");
        return deptUuid;
    }

    /**
     * 可视对讲下发 权限
     *
     * @param map
     */
    private void visualIntercomPermissions(Map<String,Object> map) {
        // TODO 目前下发的 authName权限组是我们自定义的, 后面肯定是按照小区的 期楼栋号来设置的
        // TODO longNums设备编号, 可视对讲的机器编号, 应该根据 期楼栋号 下面的机器编号来设置的

        //--------- 可视对讲 ----------

        // 可视对讲 根据人员 ID 集添加权限并下发
        HKOpenApi.addOutDoorAuth(map);

    }

    /**
     * 可视对讲 指定人员指纹权限下载
     * @param map
     */
    private void visualIntercomFingerprint(Map<String,Object> map) {
        // 可视对讲 指定人员指纹权限下载
        Map<String, Object> downloadFingerMap = new HashMap<>();
        // opType 操作类型 Integer 是 1 为下发权限；2 为删除权限
        downloadFingerMap.put("opType", 1);
        downloadFingerMap.put("personIds", map.get("personIds"));
        downloadFingerMap.put("longNums", map.get("longNums"));
        downloadFingerMap.put("openapi_ip_port_http", map.get("openapi_ip_port_http"));
        // 可视对讲 指定人员指纹权限下载
        HKOpenApi.downloadFinger(downloadFingerMap);
    }

    @Override
    public ResponseBean syncControl(Integer userVerifyId) {
        // TODO 暂时只支持开单元门

        ResponseBean responseBean = new ResponseBean();

        // 查询当前的房产
        TaUserVerify userVerify = taUserVerifyMapper.selectByPrimaryKey(userVerifyId);
        TpEquipmentTree tpEquipmentTree = tpEquipmentTreeMapper.selectByCommunityId(userVerify.getCommunityId());
        // 单元门口机
        List<TpEquipment> tpEquipments = tpEquipmentMapper.selectByCommunityIdAndUnitId(userVerify.getCommunityId(), userVerify.getUnitId(), 3);

         if (CollectionUtils.isEmpty(tpEquipments)) {
             responseBean.addError("无设备信息!");
             return responseBean;
         }

         String str = "";
         for (TpEquipment e : tpEquipments) {
             TpConfiguration tpConfiguration = tpConfigurationMapper.selectByPrimaryKey(e.getUuidId());
             str += tpConfiguration.getConfigurationValue();
             str += ",";
         }

        // 查询设备编号

        Map<String,Object> parMap = com.beust.jcommander.internal.Maps.newHashMap();
        parMap.put("longNums", str);
        parMap.put("openapi_ip_port_http", tpEquipmentTree.getHttpServer());
        parMap.put("secret", tpEquipmentTree.getSecret());
        parMap.put("appkey", tpEquipmentTree.getAppkey());
        String data = HKOpenApi.syncControl(parMap);
        JSONObject jsonObject = JSONObject.parseObject(data);
        int errorCode = jsonObject.getInteger("errorCode");
        if (errorCode == 0) {
            responseBean.addSuccess("操作成功!");
            return responseBean;
        }
        responseBean.addError("操作失败!");
        return responseBean;
    }
}
