/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.modules.dmuser.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.exception.EntityExistException;
import me.zhengjie.modules.dmuser.domain.DmUser;
import me.zhengjie.modules.dmuser.domain.Vo.DmUserVo;
import me.zhengjie.modules.system.repository.UserRepository;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.dmuser.repository.DmUserRepository;
import me.zhengjie.modules.dmuser.service.DmUserService;
import me.zhengjie.modules.dmuser.service.dto.DmUserDto;
import me.zhengjie.modules.dmuser.service.dto.DmUserQueryCriteria;
import me.zhengjie.modules.dmuser.service.mapstruct.DmUserMapper;
import me.zhengjie.ykt.domain.DmRoomDevice;
import me.zhengjie.ykt.repository.DmRoomDeviceRepository;
import me.zhengjie.ykt.service.dto.DmRoomDeviceDto;
import me.zhengjie.ykt.service.mapstruct.DmRoomDeviceMapper;
import org.apache.http.client.ClientProtocolException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

/**
 * @author AndyCheung
 * @website https://el-admin.vip
 * @description 服务实现
 * @date 2021-09-30
 **/
@Service
@RequiredArgsConstructor
@Slf4j
public class DmUserServiceImpl implements DmUserService {

    @Value("${personOperate}")
    private String personOperate;
    @Value("${zkUpdateUrl}")
    private String zkUpdateUrl;
    @Value("${headerKey}")
    private String header_key;
    private final DmUserRepository dmUserRepository;
    private final DmUserMapper dmUserMapper;
    private final DmRoomDeviceMapper dmRoomDeviceMapper;
    private final DmRoomDeviceRepository dmRoomDeviceRepository;
    private final UserRepository userRepository;
    @Value("${key}")
    private String key;// = "DMERPYT!@#$QWER2021+{:>";
    @Value("${synchronizationDeviceUrl}")
    private String SYNCHRONIZATION_DEVICE_URL;

    @Override
    public Map<String, Object> queryAll(DmUserQueryCriteria criteria, Pageable pageable) {
        Page<DmUser> page = dmUserRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(dmUserMapper::toDto));
    }

    @Override
    public List<DmUserDto> queryAll(DmUserQueryCriteria criteria) {
        return dmUserMapper.toDto(dmUserRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public DmUserDto findById(String id) {
        DmUser dmUser = dmUserRepository.findById(id).orElseGet(DmUser::new);
        ValidationUtil.isNull(dmUser.getId(), "DmUser", "id", id);
        return dmUserMapper.toDto(dmUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DmUserDto create(DmUser resources) {
        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
        resources.setId(String.valueOf(snowflake.nextId()));
        //判断邮箱是否重复
        DmUser user = dmUserRepository.findByEmail(resources.getEmail());
        if (user != null) {
            throw new EntityExistException(DmUser.class, "email", resources.getEmail());
        }
        return dmUserMapper.toDto(dmUserRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createUserDevice(DmUserVo dmUserVo) {
        //获取用户id
        List<Map<String, Object>> maps = userRepository.findAllByEnable(null, dmUserVo.getUserId());
        String userID = maps.get(0).get("userID").toString();
        //返回msg
        String msg = "{result:0}";
        //获取前端传入的设备权限集合
        List<DmRoomDevice> roomDeviceList = dmUserVo.getRoomDeviceId();
        if (!roomDeviceList.isEmpty()) {
            //开始新增
            JSONObject jsonObject = new JSONObject();
            //设置用户id
            jsonObject.put("userId", userID);
            // 设置 1 代表是新增
            jsonObject.put("operateType", 1);
            JSONArray arra = new JSONArray();
            roomDeviceList.forEach(item -> {
                for (DmRoomDevice device : roomDeviceList) {
                    if (dmUserRepository.createUserDeviceBySelect(dmUserVo.getUserId(), device.getCode(), device.getDoorID().toString(), device.getId().toString()) > 0) {
                        //开始同步增加数据
                        log.info("开始向列表同步添加设备");
                        //获取要新增的数据
                        JSONObject paramObject = new JSONObject();
                        paramObject.put("serialNumber", device.getCode());
                        paramObject.put("doorID", device.getDoorID());
                        paramObject.put("deviceType", device.getDeviceType());
                        arra.add(paramObject);
                    }
                }
            });
            jsonObject.put("deviceInfo", arra);
            log.info("添加设备列表" + arra.toJSONString());
            if (jsonObject.getJSONArray("deviceInfo").size() > 0) {
                // 日志打印 参数列表
                log.info("添加数据：" + jsonObject.toJSONString());
                msg = HttpRequest.post(SYNCHRONIZATION_DEVICE_URL).form("device", JSONObject.toJSONString(jsonObject)).execute().body();
                JSONObject msgObject = JSONObject.parseObject(msg);
                log.info("添加数据返回结果：" + msg);
                if (null != msgObject.get("result") && msgObject.getInteger("result") == 1) {
                    log.info("同步新增成功");
                }
            }
        } else {
            //获取删除的数据
            List<DmRoomDevice> dmRoomDevices = dmRoomDeviceRepository.findUserDevice(dmUserVo.getUserId(),null);
            dmUserRepository.delUserDevice(dmUserVo.getUserId(), null, null, null);
            //同步全删
            log.info("开始同步删除数据");
            JSONObject paramObject = new JSONObject();
            //设置用户id
            paramObject.put("userId", userID);
            // 设置 2 代表是删除
            paramObject.put("operateType", 2);
            JSONArray arra = new JSONArray();
            dmRoomDevices.forEach(item -> {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("serialNumber", item.getCode());
                jsonObject.put("doorID", item.getDoorID());
                jsonObject.put("deviceType", item.getDeviceType());
                arra.add(jsonObject);
            });
            paramObject.put("deviceInfo", arra);
            // 日志打印 参数列表
            log.info("删除数据列表" + paramObject.toJSONString());
            msg = HttpRequest.post(SYNCHRONIZATION_DEVICE_URL).form("device", JSONObject.toJSONString(paramObject)).execute().body();
            JSONObject jsonObject = JSONObject.parseObject(msg);
            log.info("全部删除数据返回结果：" + msg);
            if (null != jsonObject.get("result") && jsonObject.getInteger("result") == 1) {
                log.info("同步删除成功");
            }
        }
        //查询自己现在有那些设备权限
        List<DmRoomDevice> userDevice = dmRoomDeviceRepository.findUserDevice(dmUserVo.getUserId(),null);

        //需要删除的
        List<DmRoomDevice> notExistDevices = new ArrayList<>();
//        //两者进行匹配
        if (!roomDeviceList.isEmpty() && !userDevice.isEmpty()) {
            for (DmRoomDevice a : userDevice) {
                int mark = 0;
                for (DmRoomDevice b : roomDeviceList) {
                    //code 相等 并且 doorId相等
                    if (a.getCode().equals(b.getCode()) && a.getDoorID().toString().equals(b.getDoorID().toString())) {
                        mark++;
                    }
                }
                //先在A中去查B里面全部数据，如果匹配了就做标记，然后存放在存在的集合里,否则放另一个集合里
                if (mark == 0) {
                    //需要删除
                    notExistDevices.add(a);
                }
            }
        }
        /**
         * notExistDevices 是需要删除的
         */
        //如果有正常走删除添加逻辑  如果前端未传 设备id 代表着全删除
        if (!notExistDevices.isEmpty()) {
            //获取删除的数据 需要获取对方接口对应的参数
            JSONObject paramObject = new JSONObject();
            //设置用户id
            paramObject.put("userId", userID);
            // 设置 2 代表是删除
            paramObject.put("operateType", 2);
            JSONArray arra = new JSONArray();
            notExistDevices.forEach(item -> {
                //开始删除
                int del = dmUserRepository.delUserDevice(dmUserVo.getUserId(), item.getCode(), item.getDoorID().toString(), item.getId().toString());
                if (del > 0) {
                    //删除成功开始同步删除数据
                    log.info("开始同步删除数据");
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("serialNumber", item.getCode());
                    jsonObject.put("doorID", item.getDoorID());
                    jsonObject.put("deviceType", item.getDeviceType());
                    arra.add(jsonObject);
                }
            });
            paramObject.put("deviceInfo", arra);
            // 日志打印 参数列表
            log.info("删除数据：" + paramObject.toJSONString());
            msg = HttpRequest.post(SYNCHRONIZATION_DEVICE_URL).form("device", JSONObject.toJSONString(paramObject)).execute().body();
            JSONObject jsonObject = JSONObject.parseObject(msg);
            log.info("列表删除数据返回结果：" + msg);
            if (null != jsonObject.get("result") && jsonObject.getInteger("result") == 1) {
                log.info("同步删除成功");
            }
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(DmUser resources) throws Exception {
        DmUser dmUser = dmUserRepository.findById(resources.getId()).orElseGet(DmUser::new);
        ValidationUtil.isNull(dmUser.getId(), "DmUser", "id", resources.getId());
//        //判断邮箱是否重复
//        DmUser user = dmUserRepository.findByEmail(resources.getEmail());
//        if (user != null && !dmUser.getId().equals(user.getId())) {
//            throw new EntityExistException(DmUser.class, "email", resources.getEmail());
//        }

        if (resources.getPicture() != null) {
//            String url = "https://smartpark.caih.com/zkxt/api/thirdparty/v1/user/updateZkUsers";
            Map<String, Object> newToken = SecurityUtils.getToken(key);
            JSONObject param = new JSONObject();
            param.put("timestamp", newToken.get("timestamp"));
            param.put("nonce", newToken.get("nonce"));
            JSONObject data = new JSONObject();
            data.put("faceid", resources.getPicture());
            data.put("id", resources.getId());
            param.put("query", data);
            HttpRequest.get(zkUpdateUrl)
                    .header(header_key, newToken.get("token").toString())
                    .body(param.toJSONString()).execute().body();

//            String api = "http://10.208.128.14:8069/openapi/personOperate";
            JSONObject person = new JSONObject();
            person.put("userId", resources.getId());
            person.put("userName", resources.getName());
            person.put("deptId", resources.getDept().getId());
            person.put("facePicture", ImageUtil.encodeImageToBase64(new URL(resources.getPicture())));
            person.put("operateType", 2);
            String res = HttpRequest.post(personOperate)
                    .form("person", person.toJSONString()).execute().body();
            System.out.println("res:" + res);
        }
        dmUserRepository.save(resources);
    }

    @Override
    public void deleteAll(String[] ids) {
        for (String id : ids) {
            dmUserRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<DmUserDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (DmUserDto dmUser : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("姓名", dmUser.getName());
            map.put("性别", dmUser.getSex());
            map.put("邮箱地址", dmUser.getEmail());
            map.put("手机", dmUser.getContacts());
            map.put("部门", dmUser.getDept().getId());
            map.put("是否是审批人(1-是,0-否)", dmUser.getIsApprover());
            map.put("创建者", dmUser.getCreateBy());
            map.put("更新者", dmUser.getUpdateBy());
            map.put("创建日期", dmUser.getCreateTime());
            map.put("最后更新时间", dmUser.getUpdateTime());
            map.put("人员种类", dmUser.getUsertype());
            map.put("在职状态", dmUser.getEnabled());
            map.put("员工工号", dmUser.getUserNumber());
            map.put("备注", dmUser.getRemark());
            map.put("登记状态", dmUser.getStatus());
            map.put("单位", dmUser.getCompany());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public List<DmUser> findNotBindUser(String userId) {
        String param = "";
        if (userId != null && !userId.equals("")) {
            param = userId + "";
        }
        return dmUserRepository.findNotBindUser(param);
    }

    @Override
    public List<Map<String, String>> findNotUserCard(String userId) {
        String param = "";
        if (userId != null && !userId.equals("")) {
            param = userId + "";
        }
        return dmUserRepository.findNotUserCard(param);
    }

    @Override
    public Map<String, Object> homePageYktUser() {
        Map<String, Object> map = new HashMap<>();
        map.put("userPicture", dmUserRepository.userPicture());
        map.put("userCard", dmUserRepository.userCard());
        map.put("userCardLs", dmUserRepository.userCardLs());
        return map;
    }

    @Override
    public List<Map<String, Object>> findUser() {
        return dmUserRepository.findUser();
    }

    @Override
    public List<Map<String, Object>> findUserByDeptId(String deptId) {
        return dmUserRepository.findUserByDeptId(deptId);
    }

    @Override
    public DmUser findByUserNumber(String userNumber) {
        return dmUserRepository.findByUserNumber(userNumber);
    }

    @Override
    public DmUser findByUserCardId(String userNumber) {
        return dmUserRepository.findByUserCardId(userNumber);
    }

    @Override
    public DmUser findByCardId(String userNumber) {
        return dmUserRepository.findByCardId(userNumber);
    }
}