package com.sptg.gateway.controller.device;

import com.baomidou.mybatisplus.plugins.Page;
import com.sptg.common.core.beans.PageBean;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.constant.SysLogConstant;
import com.sptg.common.core.constant.UserFlagConstant;
import com.sptg.common.core.entity.DispatchTask;
import com.sptg.common.core.util.WebUtils;
import com.sptg.common.security.annotation.Security;
import com.sptg.common.security.enums.DataFormatEnum;
import com.sptg.common.security.service.SecurityServiceInterface;
import com.sptg.device.api.constant.DeviceConstants;
import com.sptg.device.api.constant.DeviceSecurityToken;
import com.sptg.device.api.dto.DeviceDto;
import com.sptg.device.api.dto.DeviceOptionsDto;
import com.sptg.device.api.dto.DeviceTemplateDto;
import com.sptg.device.api.entity.Device;
import com.sptg.device.api.entity.DeviceOptions;
import com.sptg.device.api.entity.DeviceTemplate;
import com.sptg.device.api.entity.InstructPublishLog;
import com.sptg.device.api.feigns.*;
import com.sptg.device.api.stream.DeviceDeleteProduceInterface;
import com.sptg.estate.api.entity.AccessCard;
import com.sptg.estate.api.entity.Residential;
import com.sptg.estate.api.entity.Unit;
import com.sptg.estate.api.feigns.AccessCardFeign;
import com.sptg.estate.api.feigns.ResidentialFeign;
import com.sptg.estate.api.feigns.UnitFeign;
import com.sptg.permissions.api.entity.Account;
import com.sptg.permissions.api.entity.Organization;
import com.sptg.permissions.api.feigns.OrgFeign;
import com.sptg.statistics.api.constant.SysLogMenuConstant;
import com.sptg.statistics.api.entity.SysOperationLog;
import com.sptg.statistics.api.feigns.SysOperationLogFeign;
import com.sptg.third.api.entity.qinlin.QLinUserDevice;
import com.sptg.third.api.feigns.grid.GridDoorDeviceFeign;
import com.sptg.third.api.feigns.qinlin.QLinFeign;
import feign.Param;
import lombok.AllArgsConstructor;
import org.apache.http.util.Asserts;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * title: DeviceController
 * package: com.sptg.gateway.controller.device
 * description: 设备控制器
 */
@RestController
@AllArgsConstructor
public class DeviceController {

    private final SecurityServiceInterface<Account> securityServiceInterface;
    private final DeviceFeign deviceFeign;
    private final OrgFeign orgFeign;
    private final UnitFeign unitFeign;
    private final SysOperationLogFeign sysOperationLogFeign;
    private final ResidentialFeign residentialFeign;
    private final InstructPublishLogFeign instructPublishLogFeign;
    private final DeviceTemplateFeign deviceTemplateFeign;
    private final DeviceOptionsFeign deviceOptionsFeign;
    private final AccessCardFeign accessCardFeign;
    private final MsgPublishFeign msgPublishFeign;
    private final QLinFeign qLinFeign;
    private final GridDoorDeviceFeign gridDoorDeviceFeign;

    @PostMapping(value = "/device/instruct/pagingQuery")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_MANAGE, format = DataFormatEnum.JSON)
    public ResultBean<Page> pagingQuery(
            InstructPublishLog publishLog,
            PageBean<InstructPublishLog, InstructPublishLog> pageBean) {
        Assert.hasText(publishLog.getSerialNumber(), "设备序列号不能为空");
        pageBean.setDto(publishLog);
        return this.instructPublishLogFeign.pagingQuery(pageBean);
    }

    /**
     * 功能描述: 分页查询设备列表
     *
     * @param dto      查询条件
     * @param pageBean 分页条件
     * @return ResultBean<Page>
     */
    @GetMapping(value = "/device/manage/pagingQuery")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_MANAGE, format = DataFormatEnum.JSON)
    public ResultBean<Page<Device>> pagingQuery(DeviceDto dto, PageBean<Device, DeviceDto> pageBean) {
        //  获取当前用户
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        //  如果机构ID不为空且选择的机构ID为空时，选择的机构ID赋值为机构ID
        Organization userOrg = this.orgFeign.getOrgById(onLineUser.getOrgId());
        if (dto.getOrgId() != null && dto.getSelectedId() == null) {
            dto.setSelectedId(dto.getOrgId());
        }
        if (null != dto.getSelectedId()) {
            //  权限校验
            Organization org = this.orgFeign.getOrgById(dto.getSelectedId());
            if (null == org) {
                return new ResultBean<>(ResultEnum.SUCCESS, pageBean);
            }
            if (!org.getPosition().startsWith(onLineUser.getOrgPosition())) {
                return new ResultBean<>(ResultEnum.FORBIDDEN);
            }
            if (org.getOrgType() == OperationConstant.THREE) {
                //物业
                dto.setEstatePosition(org.getPosition());
            } else {
                //机构
                dto.setOrgPosition(org.getPosition());
            }
        } else {
            if (userOrg.getOrgType() == OperationConstant.THREE) {
                //物业
                dto.setEstatePosition(onLineUser.getOrgPosition());
            } else {
                //机构
                dto.setOrgPosition(onLineUser.getOrgPosition());
            }
        }
        pageBean.setDto(dto);
        return this.deviceFeign.pagingQuery(pageBean);
    }

    /**
     * 功能描述: 添加设备
     *
     * @param dto 设备信息
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/device/manage/add")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_ADD, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> addEntity(DeviceDto dto) {
        //  数据校验 [ 序列号,设备型号,小区Id,安装位置,开门密码,人脸识别度,是否启用时间策略 ]
        Assert.notNull(dto, "参数异常");
        Assert.hasText(dto.getSerialNumber(), "设备序列号不能为空");
        Assert.notNull(dto.getXqId(), "请选择小区");
        Assert.hasText(dto.getInstallPath(), "安装位置不能为空");
        Residential residential = this.residentialFeign.findResidentialById(dto.getXqId());
        Assert.notNull(residential, "请填写正确的小区信息");
        Organization rootOrg = this.orgFeign.getOrgById(residential.getRootOrgId());
        Assert.notNull(rootOrg, "数据异常");
        //  设置小区名称
        dto.setXqName(residential.getName());
        dto.setOrgPosition(residential.getOrgPosition());
        dto.setEstatePosition(residential.getEstatePosition());
        //  位置信息
        dto.setRegionProvince(residential.getRegionProvince());
        dto.setRegionCity(residential.getRegionCity());
        dto.setRegionArea(residential.getRegionArea());
        //  跟组织信息
        dto.setRootOrgId(rootOrg.getId());
        dto.setRootOrgName(rootOrg.getName());
        //  设备名称 = 小区名称 + 单元名称 + 安装位置 + 序号
        StringBuilder name = new StringBuilder(residential.getName());
        //  获取单元信息
        if (null != dto.getUnitId()) {
            Unit unit = this.unitFeign.findUnitById(dto.getUnitId());
            Assert.notNull(unit, "请填写正确的单元信息");
            name.append(unit.getName());
            dto.setDyName(unit.getName());
            dto.setOrgPosition(unit.getOrgPosition());
        }
        name.append(dto.getInstallPath());
        dto.setName(name.toString());
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        dto.setCreateAccountId(onLineUser.getId());
        ResultBean<Boolean> resultBean = null;
        String deviceFactory = dto.getDeviceFactory();
        if(deviceFactory.equals(DeviceConstants.DEVICE_FACTORY_QINLIN)){ //如果是第三方设备，只做简单创建即可
            resultBean = this.deviceFeign.addThirdEntity(dto);
            return resultBean;
        }else{
            //获取设备模板
            DeviceTemplateDto deviceTemplateDto = new DeviceTemplateDto();
            deviceTemplateDto.setTypeCode(dto.getDeviceModelNumber());
            deviceTemplateDto.setDeviceFactory(dto.getDeviceFactory());
            DeviceTemplate deviceTemplate = this.deviceTemplateFeign.getOne(deviceTemplateDto);
            Assert.notNull(deviceTemplate, "没有与该设备型号匹配的配置模板");
            dto.setHaveCard(deviceTemplate.getHaveCard());
            dto.setHaveFace(deviceTemplate.getHaveFace());
            dto.setHaveCall(deviceTemplate.getHaveCall());
            dto.setHaveKeyboard(deviceTemplate.getHaveKeyboard());
            dto.setHaveAd(deviceTemplate.getHaveAd());
            dto.setReboot(deviceTemplate.getReboot());
            dto.setSize(deviceTemplate.getSize());
            dto.setOpenDoorPwd(deviceTemplate.getOpenDoorPwd());
            if(StringUtils.hasText(deviceTemplate.getAdminPwd())){
                dto.setAdminPwd(deviceTemplate.getAdminPwd());
            }else{
                dto.setAdminPwd("123456");
            }
            resultBean = this.deviceFeign.addEntity(dto);
            Device device = this.deviceFeign.getEntityBySerialNumber(dto.getSerialNumber());
            //生成设备配置记录
            DeviceOptionsDto deviceOptionsDto = this.generateOptions(deviceTemplate, device);
            if (!this.deviceOptionsFeign.add(deviceOptionsDto)){
                return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY,false);
            }
        }
        if (null != resultBean.getData() && resultBean.getData()) {
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            SysOperationLog sysOperationLog = new SysOperationLog(SysLogMenuConstant.DEVICE_INFO_MANAGE, SysLogConstant.ADD_EVENT,
                    WebUtils.getIp(), dto, onLineUser,dto);
            sysOperationLogFeign.info(sysOperationLog);
            /*-------------------------------------------------------------------------------------------------------------------*/

            /*---------------------------------------------------推送门禁设备到网格--------------------------------------------------------*/

            ResultBean<String> stringResultBean = this.gridDoorDeviceFeign.gridDevicePush(dto);
            if(stringResultBean != null&&stringResultBean.getData().equals("操作成功")){
                SysOperationLog sysOperationLog1=new SysOperationLog("推送门禁到网格成功", SysLogConstant.ADD_EVENT,
                        WebUtils.getIp(),resultBean.getData(),onLineUser,resultBean.getData());
                sysOperationLogFeign.info(sysOperationLog1);
            }else{
                SysOperationLog sysOperationLog1=new SysOperationLog("推送门禁数据到网格失败", SysLogConstant.ADD_EVENT,
                        WebUtils.getIp(),resultBean.getData(),onLineUser,resultBean.getData());
                sysOperationLogFeign.info(sysOperationLog1);
            }
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }

    /**
     * 功能描述: 设备分配
     *
     * @param dto 设备信息
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/device/manage/complete")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_COMPLETE, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> completeEntity(DeviceDto dto) {
		//  数据校验 [ 序列号,设备型号,小区Id,安装位置,开门密码,人脸识别度,是否启用时间策略 ]
        Assert.notNull(dto, "参数异常");
        Assert.hasText(dto.getSerialNumber(), "设备序列号不能为空");
        Assert.notNull(dto.getXqId(), "请选择小区");
        Assert.hasText(dto.getInstallPath(), "安装位置不能为空"); //比如大门
/*        Assert.hasText(dto.getOpenDoorPwd(),"开门密码不能为空");
        Assert.hasText(dto.getAdminPwd(),"设备管理密码不能为空");*/
        //  获取小区信息
//        Organization xqOrg = this.orgFeign.getOrgById(dto.getXqId());
        Residential residential = this.residentialFeign.findResidentialById(dto.getXqId());
        Assert.notNull(residential, "请填写正确的小区信息");
        Organization rootOrg = this.orgFeign.getOrgById(residential.getRootOrgId());
        Assert.notNull(rootOrg, "数据异常");
		//  设置小区名称
        dto.setXqName(residential.getName());
        dto.setOrgPosition(residential.getOrgPosition());
        dto.setEstatePosition(residential.getEstatePosition());
		//  位置信息
        dto.setRegionProvince(residential.getRegionProvince());
        dto.setRegionCity(residential.getRegionCity());
        dto.setRegionArea(residential.getRegionArea());
		//  跟组织信息
        dto.setRootOrgId(rootOrg.getId());
        dto.setRootOrgName(rootOrg.getName());
		//  设备名称 = 小区名称 + 单元名称 + 安装位置 + 序号
        StringBuilder name = new StringBuilder(residential.getName());
		//  获取单元信息
        if (null != dto.getUnitId()) {
            Unit unit = this.unitFeign.findUnitById(dto.getUnitId());
            Assert.notNull(unit, "请填写正确的单元信息");
            name.append(unit.getName());
            dto.setDyName(unit.getName());
            dto.setOrgPosition(unit.getOrgPosition());
        }
        name.append(dto.getInstallPath());
        dto.setName(name.toString());
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        dto.setCreateAccountId(onLineUser.getId());
//        dto.setOldOpenDoorPwd(dto.getOpenDoorPwd());
        //获取设备模板
        DeviceTemplateDto deviceTemplateDto = new DeviceTemplateDto();
        deviceTemplateDto.setTypeCode(dto.getDeviceModelNumber());
        deviceTemplateDto.setDeviceFactory(dto.getDeviceFactory());
        DeviceTemplate deviceTemplate = deviceTemplateFeign.getOne(deviceTemplateDto);
        Assert.notNull(deviceTemplate, "没有与该设备型号匹配的配置模板");
        dto.setHaveCard(deviceTemplate.getHaveCard());
        dto.setHaveFace(deviceTemplate.getHaveFace());
        dto.setHaveCall(deviceTemplate.getHaveCall());
        dto.setReboot(deviceTemplate.getReboot());
        dto.setHaveKeyboard(deviceTemplate.getHaveKeyboard());
        dto.setHaveAd(deviceTemplate.getHaveAd());
        dto.setSize(deviceTemplate.getSize());
        dto.setOpenDoorPwd(deviceTemplate.getOpenDoorPwd());
        if(StringUtils.hasText(deviceTemplate.getAdminPwd())){
            dto.setAdminPwd(deviceTemplate.getAdminPwd());
        }
        ResultBean<Boolean> resultBean = this.deviceFeign.completeEntity(dto);
        Device device = this.deviceFeign.getEntityBySerialNumber(dto.getSerialNumber());
		//生成设备配置记录
        DeviceOptionsDto deviceOptionsDto = this.generateOptions(deviceTemplate, device);
        if (!this.deviceOptionsFeign.add(deviceOptionsDto)) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY, false);
        }
        if (null != resultBean.getData() && resultBean.getData()) {
			/*---------------------------------------------------记录日志--------------------------------------------------------*/
            SysOperationLog sysOperationLog = new SysOperationLog(SysLogMenuConstant.DEVICE_INFO_MANAGE, SysLogConstant.ADD_EVENT,
                    WebUtils.getIp(), dto, onLineUser, dto);
            sysOperationLogFeign.info(sysOperationLog);
			/*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }
/**
     * 功能描述: 设备关联小区
     *
     * @param dto 设备信息
     * @return ResultBean<Boolean>
     */

    @PostMapping(value = "/device/manage/relate")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_RELATE,format = DataFormatEnum.JSON)
    public ResultBean<Boolean> relateEntity(DeviceDto dto){
        //  数据校验 [ 序列号,设备型号,小区Id,安装位置,开门密码,人脸识别度,是否启用时间策略 ]
        Assert.notNull(dto,"参数异常");
        Assert.hasText(dto.getSerialNumber(),"设备序列号不能为空");
        Assert.notNull(dto.getXqId(),"请选择小区");
        Assert.hasText(dto.getInstallPath(),"安装位置不能为空");
        Device oldObj = this.deviceFeign.getEntityById(dto.getId());
/*        Assert.hasText(dto.getOpenDoorPwd(),"开门密码不能为空");
        Assert.hasText(dto.getAdminPwd(),"设备管理密码不能为空");*/
        //  获取小区信息
        Residential residential = this.residentialFeign.findResidentialById(dto.getXqId());
        Assert.notNull(residential,"请填写正确的小区信息");
        Organization rootOrg = this.orgFeign.getOrgById(residential.getRootOrgId());
        Assert.notNull(rootOrg,"数据异常");
        //  设置小区名称
        dto.setXqName(residential.getName());
        dto.setOrgPosition(residential.getOrgPosition());
        dto.setEstatePosition(residential.getEstatePosition());
        //  位置信息
        dto.setRegionProvince(residential.getRegionProvince());
        dto.setRegionCity(residential.getRegionCity());
        dto.setRegionArea(residential.getRegionArea());
        //  跟组织信息
        dto.setRootOrgId(rootOrg.getId());
        dto.setRootOrgName(rootOrg.getName());
        //  设备名称 = 小区名称 + 单元名称 + 安装位置 + 序号
        StringBuilder name = new StringBuilder(residential.getName());
        //  获取单元信息
        if (null != dto.getUnitId()){
            Unit unit = this.unitFeign.findUnitById(dto.getUnitId());
            Assert.notNull(unit,"请填写正确的单元信息");
            name.append(unit.getName());
            dto.setDyName(unit.getName());
            dto.setOrgPosition(unit.getOrgPosition());
        }
        name.append(dto.getInstallPath());
        dto.setName(name.toString());
        //获取设备模板
        DeviceTemplateDto deviceTemplateDto = new DeviceTemplateDto();
        deviceTemplateDto.setTypeCode(dto.getDeviceModelNumber());
        deviceTemplateDto.setDeviceFactory(dto.getDeviceFactory());
        DeviceTemplate deviceTemplate = deviceTemplateFeign.getOne(deviceTemplateDto);
        Assert.notNull(deviceTemplate, "没有与该设备型号匹配的配置模板");
        dto.setHaveCard(deviceTemplate.getHaveCard());
        dto.setHaveFace(deviceTemplate.getHaveFace());
        dto.setHaveCall(deviceTemplate.getHaveCall());
        dto.setReboot(deviceTemplate.getReboot());
        ResultBean<Boolean> resultBean=this.deviceFeign.relateEntity(dto);
        Device device = this.deviceFeign.getEntityBySerialNumber(dto.getSerialNumber());
        //生成设备配置记录
        DeviceOptionsDto deviceOptionsDto = this.generateOptions(deviceTemplate, device);
        if (!this.deviceOptionsFeign.add(deviceOptionsDto)){
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY,false);
        }
        if(null!=resultBean.getData()&&resultBean.getData()){
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            Device newObj = this.deviceFeign.getEntityById(dto.getId());
            Account onLineUser = this.securityServiceInterface.getOnLineUser();
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.DEVICE_INFO_MANAGE, SysLogConstant.RELATE_EVENT,
                    WebUtils.getIp(),dto,onLineUser,oldObj,newObj);
            sysOperationLogFeign.info(sysOperationLog);
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }

    /**
     * 设备赋值设备配置参数
     *
     * @param deviceTemplate 设备模板
     * @param deviceOptions  设备配置
     */
    private void deviceSetOptions(DeviceTemplate deviceTemplate, DeviceOptions deviceOptions) {
        deviceOptions.setCallVolume(deviceTemplate.getCallVolume());
        deviceOptions.setAdVolume(deviceTemplate.getAdVolume());
        deviceOptions.setScreenBrightness(deviceTemplate.getScreenBrightness());
        deviceOptions.setDelay(deviceTemplate.getDelay());
        deviceOptions.setIsShowUsername(deviceTemplate.getIsShowUsername());
        deviceOptions.setFaceResolution(deviceTemplate.getFaceResolution());
        deviceOptions.setFillLight(deviceTemplate.getFillLight());
        deviceOptions.setLiveDetect(deviceTemplate.getLiveDetect());
        deviceOptions.setDiscernBoxPosition(deviceTemplate.getDiscernBoxPosition());
        deviceOptions.setPlayModel(deviceTemplate.getPlayModel());
        deviceOptions.setOpenDoorPwd(deviceTemplate.getOpenDoorPwd());
        deviceOptions.setAdminPwd(deviceTemplate.getAdminPwd());
    }

    /**
     * 生成设备配置记录
     * @param deviceTemplate    设备配置模板
     * @param device            设备
     * @return DeviceOptions
     */
    private DeviceOptionsDto generateOptions(DeviceTemplate deviceTemplate, Device device){
        DeviceOptionsDto deviceOptionsDto = new DeviceOptionsDto();
        deviceOptionsDto.setStatus(OperationConstant.ZERO);
        deviceOptionsDto.setUpdateDate(new Date());
        //device
        deviceOptionsDto.setDeviceId(device.getId());
        deviceOptionsDto.setSerialNumber(device.getSerialNumber());
        deviceOptionsDto.setTypeCode(device.getDeviceModelNumber());
        deviceOptionsDto.setDeviceFactory(device.getDeviceFactory());
        deviceOptionsDto.setTimeStrategyIsEnable(device.getTimeStrategyIsEnable());
        //deviceTemplate
        deviceOptionsDto.setCallVolume(deviceTemplate.getCallVolume());
        deviceOptionsDto.setAdVolume(deviceTemplate.getAdVolume());
        deviceOptionsDto.setScreenBrightness(deviceTemplate.getScreenBrightness());
        deviceOptionsDto.setFillLight(deviceTemplate.getFillLight());
        deviceOptionsDto.setFaceResolution(deviceTemplate.getFaceResolution());
        deviceOptionsDto.setDelay(deviceTemplate.getDelay());
        deviceOptionsDto.setIsShowUsername(deviceTemplate.getIsShowUsername());
        deviceOptionsDto.setLiveDetect(deviceTemplate.getLiveDetect());
        deviceOptionsDto.setDiscernBoxPosition(deviceTemplate.getDiscernBoxPosition());
        deviceOptionsDto.setPlayModel(deviceTemplate.getPlayModel());
        deviceOptionsDto.setOpenDoorPwd(deviceTemplate.getOpenDoorPwd());
        deviceOptionsDto.setAdminPwd(deviceTemplate.getAdminPwd());
        //设备配置功能
        deviceOptionsDto.setCardOpenDoor(OperationConstant.ONE);
        deviceOptionsDto.setFaceOpenDoor(OperationConstant.ONE);
        deviceOptionsDto.setPwdOpenDoor(OperationConstant.ONE);
        deviceOptionsDto.setRemoteOpenDoor(OperationConstant.ONE);
        deviceOptionsDto.setKeyboard(OperationConstant.ONE);
        deviceOptionsDto.setAdPlay(OperationConstant.ONE);
        if(device.getHaveCard() != OperationConstant.ONE){
            deviceOptionsDto.setCardOpenDoor(OperationConstant.TWO);
        }
        if(device.getHaveFace() != OperationConstant.ONE){
            deviceOptionsDto.setFaceOpenDoor(OperationConstant.TWO);
        }
        if(device.getHaveKeyboard() != OperationConstant.ONE){
            deviceOptionsDto.setPwdOpenDoor(OperationConstant.TWO);
            deviceOptionsDto.setKeyboard(OperationConstant.TWO);
        }
        if(device.getHaveAd() != OperationConstant.ONE){
            deviceOptionsDto.setAdPlay(OperationConstant.TWO);
        }
        return deviceOptionsDto;
    }

    /**
     * 功能描述: 获取设备信息
     *
     * @param id 设备Id
     * @return ResultBean<Device>
     */
    @GetMapping(value = "/device/manage/get/{id}")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_MANAGE, format = DataFormatEnum.JSON)
    public ResultBean<Device> getEntityById(@PathVariable(value = "id") Long id) {
        Device device = this.deviceFeign.getEntityById(id);
        if (null == device) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
        }
        return new ResultBean<>(ResultEnum.SUCCESS, device);
    }

    /**
     * 功能描述: 修改设备基本信息
     *
     * @param dto 设备基本信息
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/device/manage/edit")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_UPDATE, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> editEntity(DeviceDto dto) {
        //  参数校验
        if (null == dto || null == dto.getId()) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
        }
        Device oldObj = this.deviceFeign.getEntityById(dto.getId());
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        dto.setOrgPosition(onLineUser.getOrgPosition());
        ResultBean<Boolean> resultBean = this.deviceFeign.editEntity(dto);
        if (null != resultBean.getData() && resultBean.getData()) {
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            Device newObj = this.deviceFeign.getEntityById(dto.getId());
            SysOperationLog sysOperationLog = new SysOperationLog(SysLogMenuConstant.DEVICE_INFO_MANAGE, SysLogConstant.ALTER_EVENT,
                    WebUtils.getIp(), dto, onLineUser,oldObj,newObj);
            sysOperationLogFeign.info(sysOperationLog);
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }

    /**
     * 功能描述: 更换设备
     * @param dto 设备信息
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/device/manage/replaceDevice")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_REPLACE, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> replaceDevice(DeviceDto dto) {
        Device device = this.deviceFeign.getEntityById(dto.getId());
        dto.setAlias(device.getAlias());
        dto.setXqId(device.getXqId());
        dto.setUnitId(device.getUnitId());
        dto.setInstallPath(device.getInstallPath());
        dto.setInstallPathId(device.getInstallPathId());
        Long[] ids = new Long[1];
        ids[0] = dto.getId();
        this.delete(ids);
        return this.addEntity(dto);
    }

    /**
     * 功能描述: 批量修改
     *
     * @param dto 设备信息
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/device/manage/batch/edit")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_BATCH_UPDATE, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> batchEditEntity(@RequestBody DeviceDto dto) {
        //  参数校验
        if (null == dto.getIdList() ||
                dto.getIdList().size() <= 0 ||
                StringUtils.isEmpty(dto.getOpenDoorPwd()) ||
                null == dto.getFaceResolution() ||
                null == dto.getTimeStrategyIsEnable() ||
                null == dto.getDelay()
        ) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
        }
        //  获取当前用户
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        dto.setOrgPosition(onLineUser.getOrgPosition());
        ResultBean<Boolean> resultBean = this.deviceFeign.batchEditEntity(dto);
        if (null != resultBean.getData() && resultBean.getData()) {
            List<SysOperationLog> sysOperationLogList = new ArrayList<>();
            dto.getIdList().forEach(id -> {
                DeviceDto dto2 = new DeviceDto();
                dto2.setId(id);
                SysOperationLog sysOperationLog = new SysOperationLog(SysLogMenuConstant.DEVICE_INFO_MANAGE, SysLogConstant.ALTER_EVENT,
                        WebUtils.getIp(), dto2, onLineUser);
            });
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            sysOperationLogFeign.info(sysOperationLogList);
            /*-------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }

    /**
     * 功能描述: 设备开门
     *
     * @param device { id : 设备Id,必填 }
     * @return ResultBean<Boolean>`
     */
    @PostMapping(value = "/device/manage/open/door")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_OPEN_DOOR, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> openDoor(DeviceDto device) {
        if (null == device || null == device.getId()) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
        }
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        device.setOrgPosition(onLineUser.getOrgPosition());
        device.setUserId(UserFlagConstant.ADMIN_USER_NUMBER_FLAG + onLineUser.getId());
        if(device.getDeviceFactory().equals(DeviceConstants.DEVICE_FACTORY_QINLIN)){
            QLinUserDevice qLinUserDevice = new QLinUserDevice();
            qLinUserDevice.setUserId(UserFlagConstant.ADMIN_USER_NUMBER_FLAG + onLineUser.getId());
            qLinUserDevice.setDeviceId(device.getSerialNumber());
            ResultBean<String> resultBean = this.qLinFeign.remoteOpenDoor(qLinUserDevice);
            if(resultBean.getCode().equals("200")){
                return new ResultBean<>(ResultEnum.SUCCESS);
            }else{
                return new ResultBean<>(ResultEnum.FAILURE);
            }
        }else{
            return this.deviceFeign.openDoor(device);
        }
    }

    /**
     * 功能描述: 设备禁用
     *
     * @param deviceDto { id : 设备Id,必填 }
     * @return ResultBean<Boolean>`
     */
    @PostMapping(value = "/device/manage/disable")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_DISABLE_DEVICE, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> disableDevice(DeviceDto deviceDto) {
        if (null == deviceDto || null == deviceDto.getId()) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
        }
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        deviceDto.setOrgPosition(onLineUser.getOrgPosition());
        deviceDto.setUserId(UserFlagConstant.ADMIN_USER_FLAG + onLineUser.getId());
        Integer disableType = deviceDto.getDisableType();
        Assert.notNull(disableType, "设备禁用类型不能为空");
        return this.deviceFeign.disable(deviceDto);
    }

    /**
     * 功能描述: 远程恢复版本
     *
     * @param device { id : 设备Id,必填 }
     * @return ResultBean<Boolean>`
     */
    @PostMapping(value = "/device/manage/restore")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_RESTORE, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> restore(DeviceDto device) {
        if (null == device || null == device.getId()) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
        }
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        device.setOrgPosition(onLineUser.getOrgPosition());
        device.setUserId(UserFlagConstant.ADMIN_USER_FLAG + onLineUser.getId());
        return this.deviceFeign.restore(device);
    }

    /**
     * 功能描述: 设备格式化
     *
     * @param deviceDto { id : 设备Id,必填 }
     * @return ResultBean<Boolean>`
     */
    @PostMapping(value = "/device/manage/format/data")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_FORMAT_DATA, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> formatData(DeviceDto deviceDto) {
        if (null == deviceDto || null == deviceDto.getId()) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
        }
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        deviceDto.setOrgPosition(onLineUser.getOrgPosition());
        deviceDto.setUserId(UserFlagConstant.ADMIN_USER_FLAG + onLineUser.getId());
        String deviceFactory = deviceDto.getDeviceFactory();
        Asserts.notBlank(deviceFactory, "设备厂家不能为空");
        if (deviceFactory.equals(DeviceConstants.DEVICE_FACTORY_DAHAO)) {
            return deviceFeign.dhFormatData(deviceDto);
        } else {
            return this.deviceFeign.formatData(deviceDto);
        }
    }

    /**
     * 功能描述: 设备重启
     *
     * @param device { id : 设备Id,必填 }
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/device/manage/restart")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_RELOAD, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> restart(Device device) {
        if (null == device || null == device.getId()) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
        }
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        device.setOrgPosition(onLineUser.getOrgPosition());
        return this.deviceFeign.restart(device);
    }

    /**
     * 功能描述: 检测设备在线指令
     *
     * @param device { id : 设备Id,必填 }
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/device/manage/check/online")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_CHECK_ONLINE, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> checkOnline(Device device) {
        if (null == device || null == device.getId()) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
        }
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        device.setOrgPosition(onLineUser.getOrgPosition());
        return this.deviceFeign.checkOnline(device);
    }

    private final DeviceDeleteProduceInterface deviceDeleteProduceInterface;

    /**
     * 删除设备
     *
     * @param deviceIds 设备Id列表
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/device/manage/delete")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_DELETE, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> delete(Long[] deviceIds) {
        Assert.isTrue(null != deviceIds && deviceIds.length > 0, "设备Id不能为空");
        Message<List<Long>> build = MessageBuilder.withPayload(Arrays.asList(deviceIds)).build();
        this.deviceDeleteProduceInterface.output().send(build);
        return new ResultBean<>(ResultEnum.SUCCESS);
    }

    /**
     * 设备数据同步
     *
     * @param dto 设备信息
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/device/manage/sync/data")
    @Security(token = DeviceSecurityToken.DEVICE_DATA_SYNC, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> syncData(DeviceDto dto) {
        Assert.notNull(dto, "参数异常");
        Assert.notNull(dto.getId(), "设备Id不能为空");
        Assert.notNull(dto.getSyncMethod(), "同步方式不能为空");
        return this.deviceFeign.syncData(dto);
    }

    /**
     * 大豪设备数据同步
     * 只同步用户卡号
     *
     * @param dto 设备信息
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/device/manage/dh/sync/data")
    @Security(token = DeviceSecurityToken.DEVICE_DATA_SYNC, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> dhSyncData(DeviceDto dto) {
        Assert.notNull(dto, "参数异常");
        Assert.notNull(dto.getId(), "设备Id不能为空");
        Device device = deviceFeign.getEntityById(dto.getId());
        PageBean<AccessCard, Device> parameter = new PageBean<>();
        parameter.setDto(device);
        Page<AccessCard> accessCardPage = this.accessCardFeign.pagingQuery(parameter);
        DispatchTask task = new DispatchTask();
        task.setSerialNumber(dto.getSerialNumber());
        task.setUnitId(device.getUnitId());
        task.setXqId(device.getXqId());
        task.setSerialNumber(device.getSerialNumber());
        task.setData(accessCardPage.getRecords());
        return this.deviceFeign.pushCardsToDHDevice(task);
    }

    /**
     * 获取用户人脸日志
     *
     * @param publishLog（publishData附带userId信息，用于匹配过滤）
     * @param pageBean
     * @return
     */
    @PostMapping(value = "/device/instruct/pageFace")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_MANAGE, format = DataFormatEnum.JSON)
    public ResultBean<Page> pageFace(InstructPublishLog publishLog, PageBean<InstructPublishLog, InstructPublishLog> pageBean) {
        pageBean.setDto(publishLog);
        return this.instructPublishLogFeign.pageFace(pageBean);
    }


    /**
     * 获取用户卡片日志
     *
     * @param publishLog（publishData附带cardNo信息，用于匹配过滤）
     * @param pageBean
     * @return
     */
    @PostMapping(value = "/device/instruct/pageCard")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_MANAGE, format = DataFormatEnum.JSON)
    public ResultBean<Page> pageCard(InstructPublishLog publishLog, PageBean<InstructPublishLog, InstructPublishLog> pageBean) {
        pageBean.setDto(publishLog);
        return this.instructPublishLogFeign.pageCard(pageBean);
    }

    /**
     * 功能描述: 获取设备信息
     *
     * @param serialNumber 设备序列号
     * @return ResultBean<Device>
     */
    @GetMapping(value = "/device/manage/getDeviceBySerialNumber")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_MANAGE, format = DataFormatEnum.JSON)
    public ResultBean<Device> getDeviceBySerialNumber(@Param("serialNumber") String serialNumber) {
        Device device = this.deviceFeign.getEntityBySerialNumber(serialNumber);
        return new ResultBean<>(ResultEnum.SUCCESS, device);
    }

    /**
     * 功能描述: 指令重发
     *
     * @param instructId 指令id
     * @return ResultBean<Device>
     */
    @GetMapping(value = "/device/instruct/resend/{instructId}")
    @Security(token = DeviceSecurityToken.DEVICE_INSTRUCT_PUSH_LOG_RESEND, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> instructResend(@PathVariable(value = "instructId") Long instructId) {
        InstructPublishLog instructLog = this.instructPublishLogFeign.getById(instructId);
        if (null == instructLog) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
        }
        String serialNumber = instructLog.getSerialNumber();
        Asserts.notEmpty(serialNumber, "设备序列号不存在，无法重发指令");
        Device device = this.deviceFeign.getEntityBySerialNumber(serialNumber);
        Asserts.notNull(device, "设备不存在，无法重发指令");
        ResultBean<Boolean> resultBean = this.msgPublishFeign.resendInstruct(instructLog);
        return resultBean;
    }

    /**
     * 功能描述: 指令批量重发
     *
     * @param serialNumber 设备序列号
     * @return ResultBean<Device>
     */
    @PostMapping(value = "/device/instruct/resend/list")
    @Security(token = DeviceSecurityToken.DEVICE_INSTRUCT_PUSH_LOG_RESEND, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> instructResendBatch(@RequestBody String serialNumber) {
        Asserts.notEmpty(serialNumber, "参数不能为空");
        //筛选日志，条件设备序列号和处理状态
        InstructPublishLog instructPublishLog = new InstructPublishLog();
        instructPublishLog.setSerialNumber(serialNumber);
        List<InstructPublishLog> instructPublishLogList = this.instructPublishLogFeign.findInstructPublishLogByCondition(instructPublishLog);
        ResultBean<Boolean> resultBean = new ResultBean<>(ResultEnum.SUCCESS);
        for (InstructPublishLog publishLog : instructPublishLogList) {
            Device device = this.deviceFeign.getEntityBySerialNumber(serialNumber);
            Asserts.notNull(device, "设备不存在，无法重发指令");
            resultBean = this.msgPublishFeign.resendInstruct(publishLog);
            if (!resultBean.getData()) {
                continue;
            }
        }
        return resultBean;
    }
/**
     * 功能描述: 设备操作页面
     *
     * @return ModelAndView
     */

    @GetMapping(value = "/device/operatingView/{id}")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_MANAGE,format = DataFormatEnum.VIEW)
    public ModelAndView operatingView(@PathVariable(value = "id") Long id){
        Device device = this.deviceFeign.getEntityById(id);
        if (device == null){
            return new ModelAndView("common/404");
        }
        return new ModelAndView("device/device-operating").addObject("device",device);
    }

    /**
     * 功能描述: 设备远程信息获取
     *
     * @param device { id : 设备Id,必填 }
     * @return ResultBean<Boolean>
     */
    @PostMapping(value = "/device/manage/info/obtain")
    @Security(token = DeviceSecurityToken.DEVICE_INFO_OBTAIN, format = DataFormatEnum.JSON)
    public ResultBean<Boolean> obtainInfo(Device device) {
        if (null == device || null == device.getId()) {
            return new ResultBean<>(ResultEnum.PARAMETER_ANOMALY);
        }
        Account onLineUser = this.securityServiceInterface.getOnLineUser();
        device.setOrgPosition(onLineUser.getOrgPosition());
        return this.deviceFeign.obtainInfo(device);
    }
}
