package cn.iocoder.yudao.module.pms.controller.admin;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONObject;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.SortablePageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.pms.ThingsModelDTO;
import cn.iocoder.yudao.module.pms.controller.admin.iotdeviceallotlog.vo.IotDeviceAllotSaveReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotdeviceperson.vo.IotDevicePersonRelationSaveReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.stat.DeptUtil;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceSaveReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceSimpleRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.excel.DeviceImportExcelVO;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.vo.DevicePageReqVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotProductClassifyDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.alarm.IotAlarmSettingDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.failure.IotFailureReportDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.ly.LyDeviceDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.yanfan.YfDeviceDO;
import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.TDDeviceMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.alarm.IotAlarmSettingMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.ly.LyDeviceMapper;
import cn.iocoder.yudao.module.pms.enums.common.IotDeviceStatusEnum;
import cn.iocoder.yudao.module.pms.oa.OaFlow;
import cn.iocoder.yudao.module.pms.service.DeviceServiceImpl;
import cn.iocoder.yudao.module.pms.service.IotDeviceService;
import cn.iocoder.yudao.module.pms.service.IotProductClassifyService;
import cn.iocoder.yudao.module.pms.service.failure.IotFailureReportService;
import cn.iocoder.yudao.module.pms.service.iotbom.IotBomService;
import cn.iocoder.yudao.module.pms.service.iotdeviceallotlog.IotDeviceAllotLogService;
import cn.iocoder.yudao.module.pms.service.iotdeviceperson.IotDevicePersonService;
import cn.iocoder.yudao.module.pms.service.iotmodel.IotModelService;
import cn.iocoder.yudao.module.pms.service.yanfan.YfDeviceService;
import cn.iocoder.yudao.module.pms.util.IotDeviceConvert;
import cn.iocoder.yudao.module.supplier.dal.dataobject.product.SupplierDO;
import cn.iocoder.yudao.module.supplier.service.product.SupplierService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;


@Tag(name = "管理后台 - 设备台账")
@RestController(value = "PMSIotDeviceController")
@RequestMapping("/rq/iot-device")
@Validated
public class IotDeviceController {

    @Resource
    private IotDeviceService iotDeviceService;
    @Resource
    private DeptService deptService;
    @Resource
    private DictDataService dictDataService;
    @Resource
    private SupplierService supplierService;
    @Resource
    private IotProductClassifyService iotProductClassifyService;
    @Resource
    private IotModelService iotModelService;
    @Resource
    private IotBomService iotBomService;
    @Autowired
    private YfDeviceService yfDeviceService;
    @Autowired
    private DeviceServiceImpl deviceServiceImpl;
    @Autowired
    private IotDevicePersonService iotDevicePersonService;
    @Autowired
    private IotDeviceAllotLogService iotDeviceAllotLogService;
    @Autowired
    private IotFailureReportService iotFailureReportService;
    @Resource
    private DeptApi deptApi;
    @Autowired
    private DeptUtil deptUtil;
    @Autowired
    private IotDeviceMapper iotDeviceMapper;
    @Autowired
    private IotAlarmSettingMapper iotAlarmSettingMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private LyDeviceMapper lyDeviceMapper;

    @GetMapping(value = {"/company"})
    @Operation(summary = "获取设备属于哪个公司", description = "获取设备属于哪个公司")
    public CommonResult<String> getDeviceCompany(@RequestParam Long id) {
        IotFailureReportDO failureReport = iotFailureReportService.getIotFailureReport(id);
        String maxCode = iotDeviceService.getDeviceCompany(failureReport.getDeviceId());
        return success(maxCode);
    }

    @GetMapping(value = {"/company/{id}"})
    @Operation(summary = "获取设备属于哪个公司", description = "获取设备属于哪个公司")
    public CommonResult<String> getDeviceCompanyById(@PathVariable("id") Long id) {
//        IotFailureReportDO failureReport = iotFailureReportService.getIotFailureReport(id);
        String maxCode = iotDeviceService.getDeviceCompany(id);
        return success(maxCode);
    }

    @PostMapping("/create")
    @Operation(summary = "创建设备台账")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:create')")
    public CommonResult<Long> createIotDevice(@Valid @RequestBody IotDeviceSaveReqVO createReqVO) {
        return success(iotDeviceService.createIotDevice(createReqVO));
    }

    @GetMapping(value = {"/max"})
    @Operation(summary = "获取最大的编码", description = "获取最大的编码")
    public CommonResult<String> getMaxYfCode(@RequestParam String yfCode) {
        String maxCode = iotDeviceService.getMaxCode(yfCode);
        return success(maxCode);
    }

    @PostMapping("/saveDeviceStatuses")
    @Operation(summary = "批量调整设备状态")
    @PreAuthorize("@ss.hasPermission('pms:iot-device-status-log:create')")
    public CommonResult<Long> saveDeviceStatuses(@Valid @RequestBody List<IotDevicePersonRelationSaveReqVO> reqVOS) {
        return success(iotDevicePersonService.saveDeviceStatuses(reqVOS));
    }

    @PostMapping("/saveDeviceAllot")
    @Operation(summary = "设备调拨")
    @PreAuthorize("@ss.hasPermission('pms:iot-device-allot-log:create')")
    public CommonResult<Long> saveDeviceAllot(@Valid @RequestBody List<IotDeviceAllotSaveReqVO> reqVOS) {
        return success(iotDeviceAllotLogService.saveDeviceAllot(reqVOS));
    }

    @PutMapping("/update")
    @Operation(summary = "更新设备台账")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:update')")
    public CommonResult<Boolean> updateIotDevice(@Valid @RequestBody IotDeviceSaveReqVO updateReqVO) {
        iotDeviceService.updateIotDevice(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除设备台账")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('rq:iot-device:delete')")
    public CommonResult<Boolean> deleteIotDevice(@RequestParam("id") Long id) {
        iotDeviceService.deleteIotDevice(id);
        return success(true);
    }

    @GetMapping("/get/td")
    @Operation(summary = "获得设备台账")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<List<ThingsModelDTO>> getIotDeviceTd(@RequestParam("id") Long id) {
        IotDeviceDO iotDevice = iotDeviceService.getIotDevice(id);
        List<ThingsModelDTO> tdParams = iotDeviceService.getTdParams(iotDevice);
        return success(tdParams);
    }

    @GetMapping("/get/gateway/td")
    @Operation(summary = "获得网关属性")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<List<ThingsModelDTO>> getIotDeviceTdGateway(@RequestParam("id") Long id) {
        IotDeviceDO iotDevice = iotDeviceService.getIotDevice(id);
        List<ThingsModelDTO> tdParams = iotDeviceService.getTdGatewayParams(iotDevice);
        List<IotAlarmSettingDO> settings = iotAlarmSettingMapper.selectList("device_id", id);
        tdParams.forEach(e ->{
            settings.stream().filter(f -> f.getPropertyCode().equals(e.getIdentifier())).findFirst().ifPresent(g ->{
                e.setAlarmSettingId(g.getId());
                e.setMaxValue(g.getMaxValue());
                e.setMinValue(g.getMinValue());
            });
        });
        return success(tdParams);
    }

    @GetMapping("/get/zhbd/td")
    @Operation(summary = "获得网关属性")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<List<ThingsModelDTO>> getIotDeviceTdZhbd(@RequestParam("id") Long id) {
        IotDeviceDO iotDevice = iotDeviceService.getIotDevice(id);
        List<ThingsModelDTO> tdParams = iotDeviceService.getTdZhbdParams(iotDevice);
        return success(tdParams);
    }

    @GetMapping("/get")
    @Operation(summary = "获得设备台账")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<IotDeviceRespVO> getIotDevice(@RequestParam("id") Long id) {
        IotDeviceDO iotDevice = iotDeviceService.getIotDevice(id);
        IotDeviceRespVO iotDeviceRespVO = new IotDeviceRespVO();
        BeanUtils.copyProperties(iotDevice, iotDeviceRespVO);
//        DictDataDO dictData = dictDataService.getDictData(iotDevice.getBrand());
//        iotDeviceRespVO.setBrandName(Objects.nonNull(dictData)?dictData.getLabel():"");
        SupplierDO supplierDO = supplierService.get(iotDevice.getSupplierId());
        iotDeviceRespVO.setSupplierName(Objects.nonNull(supplierDO)?supplierDO.getName():"");
        SupplierDO supplierDO1 = supplierService.get(iotDevice.getManufacturerId());
        iotDeviceRespVO.setZzName(Objects.nonNull(supplierDO1)?supplierDO1.getName():"");
        DeptDO dept = deptService.getDept(iotDeviceRespVO.getDeptId());
        iotDeviceRespVO.setDeptName(Objects.nonNull(dept)?dept.getName():"");
        IotProductClassifyDO iotProductClassify = iotProductClassifyService.getIotProductClassify(iotDevice.getAssetClass());
        iotDeviceRespVO.setAssetClassName(Objects.nonNull(iotProductClassify)?iotProductClassify.getName():"");
//        List<YfDeviceDO> allDevice = yfDeviceService.getAllDevice();
//        allDevice.stream().filter(e -> e.getSerialNumber().equals(iotDevice.getDeviceCode())).findFirst().ifPresent(e -> {
//            iotDeviceRespVO.setIfInline(e.getStatus());
//            List<DeviceVO> deviceVOS = deviceMapper.selectNew(e.getSerialNumber());
//            if (CollUtil.isNotEmpty(deviceVOS)) {
//                Timestamp ts = deviceVOS.get(0).getTs();
//                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                String format = sdf.format(ts);
//                iotDeviceRespVO.setLastInlineTime(format);
//            }
//        });
        Map<Long, String> iotDevicePerson = iotDevicePersonService.getIotDevicePerson(ImmutableList.of(id));
        if (Objects.nonNull(iotDevicePerson)) {
            iotDeviceRespVO.setResponsibleNames(iotDevicePerson.get(id));
        }
        return success(iotDeviceRespVO);
    }

    @GetMapping("/all/params")
    @Operation(summary = "获得设备台账信息")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<List<IotDeviceDO>> getIotDeviceAllParams(@Valid IotDevicePageReqVO pageReqVO) {
        return success(iotDeviceService.getAllDevices(pageReqVO));
    }

    @GetMapping("/page")
    @Operation(summary = "获得设备台账分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> getIotDevicePage(@Valid IotDevicePageReqVO pageReqVO, @Valid SortablePageParam pageParam) {
        if (Objects.nonNull(pageParam)&&CollUtil.isNotEmpty(pageParam.getSortingFields())) {
            pageParam.getSortingFields().get(0).setField("sortColumn");
        }
        PageResult<IotDeviceDO> pageResult = iotDeviceService.getIotDevicePage(pageReqVO, pageParam);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(pageResult.getList(), IotDeviceDO::getDeptId));
        // 查询当前分页的设备是否已经设置了 保养BOM
        List<Long> deviceIds = convertList(pageResult.getList(), IotDeviceDO::getId);
        IotDevicePageReqVO reqVO = new IotDevicePageReqVO();
        reqVO.setDeviceIds(deviceIds);
        reqVO.setBomFlag("b");
        List<IotDeviceRespVO> devicesWithBoms = iotDeviceService.deviceAssociateBomList(reqVO);
        Map<Long, List<IotDeviceRespVO>> devicesWithBomsPair = new HashMap<>();
        if (CollUtil.isNotEmpty(devicesWithBoms)) {
            devicesWithBoms.forEach(bom -> {
                if (devicesWithBomsPair.containsKey(bom.getId())) {
                    List<IotDeviceRespVO> tempDevices = devicesWithBomsPair.get(bom.getId());
                    tempDevices.add(bom);
                    devicesWithBomsPair.put(bom.getId(), tempDevices);
                } else {
                    List<IotDeviceRespVO> tempDevices = new ArrayList<>();
                    tempDevices.add(bom);
                    devicesWithBomsPair.put(bom.getId(), tempDevices);
                }
            });
        }
        List<IotDeviceRespVO> iotDeviceRespVOS = IotDeviceConvert.INSTANCE.convertList(pageResult.getList(), deptMap);
        iotDeviceRespVOS.forEach(e ->{
            SupplierDO supplierDO = supplierService.get(e.getManufacturerId());
            if (Objects.nonNull(supplierDO)) {
                e.setManufacturer(supplierDO.getName());
            }
            // 设置保养项标识
            if (devicesWithBomsPair.containsKey(e.getId())) {
                e.setHasSetMaintenanceBom(true);
            }
            Map<Long, String> iotDevicePerson = iotDevicePersonService.getIotDevicePerson(ImmutableList.of(e.getId()));
            if (Objects.nonNull(iotDevicePerson)) {
                e.setChargeName(iotDevicePerson.get(e.getId()));
            }
            if (Objects.nonNull(e.getAssetClass())) {
                IotProductClassifyDO iotProductClassify = iotProductClassifyService.getIotProductClassify(e.getAssetClass());
                e.setAssetClassName(Objects.nonNull(iotProductClassify)?iotProductClassify.getName():"");
            }
        });
        return success(new PageResult<>(iotDeviceRespVOS,
                pageResult.getTotal()));
    }

    @GetMapping("/page/app")
    @Operation(summary = "获得app端设备台账分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> getAppIotDevicePage(@Valid IotDevicePageReqVO pageReqVO, @Valid SortablePageParam pageParam) {
        if (Objects.nonNull(pageParam)&&CollUtil.isNotEmpty(pageParam.getSortingFields())) {
            pageParam.getSortingFields().get(0).setField("sortColumn");
        }
        PageResult<IotDeviceDO> pageResult = iotDeviceService.getIotDevicePageApp(pageReqVO, pageParam);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(pageResult.getList(), IotDeviceDO::getDeptId));
        // 查询当前分页的设备是否已经设置了 保养BOM
        List<Long> deviceIds = convertList(pageResult.getList(), IotDeviceDO::getId);
        IotDevicePageReqVO reqVO = new IotDevicePageReqVO();
        reqVO.setDeviceIds(deviceIds);
        reqVO.setBomFlag("b");
        List<IotDeviceRespVO> devicesWithBoms = iotDeviceService.deviceAssociateBomList(reqVO);
        Map<Long, List<IotDeviceRespVO>> devicesWithBomsPair = new HashMap<>();
        if (CollUtil.isNotEmpty(devicesWithBoms)) {
            devicesWithBoms.forEach(bom -> {
                if (devicesWithBomsPair.containsKey(bom.getId())) {
                    List<IotDeviceRespVO> tempDevices = devicesWithBomsPair.get(bom.getId());
                    tempDevices.add(bom);
                    devicesWithBomsPair.put(bom.getId(), tempDevices);
                } else {
                    List<IotDeviceRespVO> tempDevices = new ArrayList<>();
                    tempDevices.add(bom);
                    devicesWithBomsPair.put(bom.getId(), tempDevices);
                }
            });
        }
        List<IotDeviceRespVO> iotDeviceRespVOS = IotDeviceConvert.INSTANCE.convertList(pageResult.getList(), deptMap);
        iotDeviceRespVOS.forEach(e ->{
            // 设置保养项标识
            if (devicesWithBomsPair.containsKey(e.getId())) {
                e.setHasSetMaintenanceBom(true);
            }
        });
        return success(new PageResult<>(iotDeviceRespVOS, pageResult.getTotal()));
    }

    @GetMapping("/getDevicesByDepts")
    @Operation(summary = "项目-任务 根据选择的部门筛选设备 忽略数据权限")
    public CommonResult<List<IotDeviceSimpleRespVO>> getDevicesByDepts(@Valid IotDevicePageReqVO reqVO) {
        List<IotDeviceDO> list = iotDeviceService.getDevicesByDepts(reqVO);
        // 查询设备的所有责任人列表
        return success(new ArrayList<>(buildDeviceSimpleListNoPermission(list)));
    }

    @GetMapping({"/list-all-simple", "/simple-list"})
    @Operation(summary = "获取设备精简信息列表", description = "只包含被开启的设备，主要用于前端的下拉选项")
    public CommonResult<List<IotDeviceSimpleRespVO>> getSimpleDeviceList(@Valid IotDevicePageReqVO reqVO) {
        List<IotDeviceDO> list = iotDeviceService.getSimpleDeviceList(reqVO);
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(convertList(list, IotDeviceDO::getDeptId));
        // 查询设备的所有责任人列表
        return success(new ArrayList<>(buildDeviceSimpleList(list)));
        // return success(new ArrayList<>(IotDeviceConvert.INSTANCE.convertSimpleLists(list, deptMap)));
    }

    @GetMapping("/responsiblePage")
    @Operation(summary = "获得设备关联责任人 分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> responsiblePage(@Valid IotDevicePageReqVO pageReqVO) {
        // 只显示已经设置关联了责任人的设备
        PageResult<IotDeviceRespVO> pageResult = iotDeviceService.personRelationDevices(pageReqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        return success(new PageResult<>(buildDevicePersonsList(pageResult.getList()), pageResult.getTotal()));
    }

    @GetMapping("/statusRelationDevices")
    @Operation(summary = "查询是否调整过状态的设备列表 分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> statusRelationDevices(@Valid IotDevicePageReqVO pageReqVO) {
        // 查询是否调整过状态的设备列表 分页
        PageResult<IotDeviceRespVO> pageResult = iotDeviceService.statusRelationDevices(pageReqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        return success(new PageResult<>(buildDeviceStatusList(pageResult.getList()), pageResult.getTotal()));
    }

    @GetMapping("/allotRelationDevices")
    @Operation(summary = "查询是否发生过调拨的设备列表 分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> allotRelationDevices(@Valid IotDevicePageReqVO pageReqVO) {
        // 查询是否发生过调拨的设备列表 分页
        PageResult<IotDeviceRespVO> pageResult = iotDeviceService.allotRelationDevices(pageReqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        return success(new PageResult<>(buildDeviceStatusList(pageResult.getList()), pageResult.getTotal()));
    }

    @GetMapping("/deviceDynamicsPage")
    @Operation(summary = "获得设备动态 分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> responsiblePagedeviceDynamicsPage(@Valid IotDevicePageReqVO pageReqVO, @Valid SortablePageParam pageParam) {
        PageResult<IotDeviceDO> pageResult = iotDeviceService.getIotDevicePage(pageReqVO, pageParam);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        return success(new PageResult<>(buildDeviceDynamicsList(pageResult.getList()), pageResult.getTotal()));
    }

    @Autowired
    private TDDeviceMapper deviceMapper;

    @GetMapping("/td/page")
    @Operation(summary = "获得设备台账包含数采信息")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> getIotDeviceTdPage(@Valid IotDevicePageReqVO pageReqVO) {
        List<String> codes = new ArrayList<>();
        if (Objects.nonNull(pageReqVO.getIfInline())&&pageReqVO.getIfInline()==0) {
            pageReqVO.setIfInline(null);
        }
        PageResult<IotDeviceDO> pageResult = iotDeviceService.getIotDeviceTdPage(pageReqVO, codes);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(pageResult.getList(), IotDeviceDO::getDeptId));
        PageResult<IotDeviceRespVO> result = new PageResult<>(IotDeviceConvert.INSTANCE.convertList(pageResult.getList(), deptMap),
                pageResult.getTotal());
        for (IotDeviceRespVO iotDeviceRespVO : result.getList()) {
            IotProductClassifyDO iotProductClassify = iotProductClassifyService.getIotProductClassify(iotDeviceRespVO.getAssetClass());
            iotDeviceRespVO.setAssetClassName(iotProductClassify.getName());
        }

        return success(result);
    }

    @GetMapping("/ly/device")
    @Operation(summary = "查询某部门下的连油设备")
    public CommonResult<List<IotDeviceDO>> getDeptLyDevice(Long deptId) {
        //获取数采yf里面的设备
        DevicePageReqVO devicePageReqVO = new DevicePageReqVO();
        devicePageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        //连油设备
        devicePageReqVO.setProductId(649L);
        List<String> codes = yfDeviceService.getDevicePage(devicePageReqVO).getList().stream().map(YfDeviceDO::getSerialNumber).collect(Collectors.toList());
        List<IotDeviceDO> iotDeviceDOS;
        if (Objects.isNull(deptId)) {
            deptId = SecurityFrameworkUtils.getLoginUserDeptId();
        }
        Set<Long> ids;
        ids = deptService.getChildDeptIdListFromCache(deptId);
        ids.add(deptId);
        IotDevicePageReqVO reqVO = new IotDevicePageReqVO();
        reqVO.setDeptIds(new ArrayList<>(ids));
        List<IotDeviceDO> devicesByDepts = iotDeviceService.getDevicesByDepts(reqVO);
        iotDeviceDOS = devicesByDepts.stream().filter(e -> codes.contains(e.getDeviceCode())).collect(Collectors.toList());
        return success(iotDeviceDOS);
    }

    @GetMapping("/td/ly/page")
    @Operation(summary = "获取包含数采的连油曲线")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> getIotDeviceTdPageLy(@Valid IotDevicePageReqVO pageReqVO) {
        DevicePageReqVO devicePageReqVO = new DevicePageReqVO();
//        devicePageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        if (Objects.nonNull(pageReqVO.getIfInline())&&pageReqVO.getIfInline()==0) {
            pageReqVO.setIfInline(null);
        }
        //连油设备
        devicePageReqVO.setProductId(649L);
        List<YfDeviceDO> list = yfDeviceService.getDevicePage(devicePageReqVO).getList();
        List<String> codes = list.stream().map(YfDeviceDO::getSerialNumber).collect(Collectors.toList());
//        List<String> codes = yfDeviceService.getDevicePage(devicePageReqVO).getList().stream().map(YfDeviceDO::getSerialNumber).collect(Collectors.toList());
        PageResult<IotDeviceDO> pageResult = iotDeviceService.getIotDeviceTdPage(pageReqVO, codes);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(pageResult.getList(), IotDeviceDO::getDeptId));
        PageResult<IotDeviceRespVO> result = new PageResult<>(IotDeviceConvert.INSTANCE.convertList(pageResult.getList(), deptMap),
                pageResult.getTotal());
        for (IotDeviceRespVO iotDeviceRespVO : result.getList()) {
            IotProductClassifyDO iotProductClassify = iotProductClassifyService.getIotProductClassify(iotDeviceRespVO.getAssetClass());
            iotDeviceRespVO.setAssetClassName(iotProductClassify.getName());
            DeptRespDTO dept = deptApi.getDept(iotDeviceRespVO.getDeptId());
            iotDeviceRespVO.setDeviceName(Objects.nonNull(dept)?dept.getName()+" "+iotDeviceRespVO.getDeviceName():iotDeviceRespVO.getDeviceName());
            list.stream().filter(e -> e.getSerialNumber().equals(iotDeviceRespVO.getDeviceCode())).findFirst().ifPresent(e ->{
                iotDeviceRespVO.setMqttUrl("/"+e.getProductId()+"/"+iotDeviceRespVO.getDeviceCode()+"/property/post");
            });
        }

        return success(result);
    }

    @GetMapping("/td/ly/screen")
    @Operation(summary = "连油看板的设备信息")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> getIotDeviceTdLyScreen(@Valid IotDevicePageReqVO pageReqVO) {
        DevicePageReqVO devicePageReqVO = new DevicePageReqVO();
        devicePageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        if (Objects.nonNull(pageReqVO.getIfInline())&&pageReqVO.getIfInline()==0) {
            pageReqVO.setIfInline(null);
        }
        //连油设备
        devicePageReqVO.setProductId(649L);
        List<YfDeviceDO> list = yfDeviceService.getDevicePage(devicePageReqVO).getList();
        List<String> codes = list.stream().map(YfDeviceDO::getSerialNumber).collect(Collectors.toList());
        PageResult<IotDeviceDO> pageResult = iotDeviceService.getIotDeviceTdPage(pageReqVO, codes);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(pageResult.getList(), IotDeviceDO::getDeptId));
        PageResult<IotDeviceRespVO> result = new PageResult<>(IotDeviceConvert.INSTANCE.convertList(pageResult.getList(), deptMap),
                pageResult.getTotal());
        for (IotDeviceRespVO iotDeviceRespVO : result.getList()) {
            IotProductClassifyDO iotProductClassify = iotProductClassifyService.getIotProductClassify(iotDeviceRespVO.getAssetClass());
            iotDeviceRespVO.setAssetClassName(iotProductClassify.getName());
            DeptRespDTO dept = deptApi.getDept(iotDeviceRespVO.getDeptId());
            iotDeviceRespVO.setDeviceName(Objects.nonNull(dept)?dept.getName()+" "+iotDeviceRespVO.getDeviceName():iotDeviceRespVO.getDeviceName());
            list.stream().filter(e -> e.getSerialNumber().equals(iotDeviceRespVO.getDeviceCode())).findFirst().ifPresent(e ->{
                iotDeviceRespVO.setMqttUrl("/"+e.getProductId()+"/"+iotDeviceRespVO.getDeviceCode()+"/property/post");
            });
            List<LyDeviceDO> deviceId = lyDeviceMapper.selectList("device_id", iotDeviceRespVO.getId());
            if (CollUtil.isNotEmpty(deviceId)) {
                iotDeviceRespVO.setOtherName(deviceId.get(0).getOtherName());
            }
        }

        return success(result);
    }


    @GetMapping("/td/page/app")
    @Operation(summary = "获得设备台账包含数采信息")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> getIotDeviceTdPageApp(@Valid IotDevicePageReqVO pageReqVO) {
        List<String> codes = new ArrayList<>();
        PageResult<IotDeviceDO> pageResult = iotDeviceService.getIotDeviceTdPageApp(pageReqVO, codes);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(pageResult.getList(), IotDeviceDO::getDeptId));
        PageResult<IotDeviceRespVO> result = new PageResult<>(IotDeviceConvert.INSTANCE.convertList(pageResult.getList(), deptMap),
                pageResult.getTotal());
        for (IotDeviceRespVO iotDeviceRespVO : result.getList()) {
            IotProductClassifyDO iotProductClassify = iotProductClassifyService.getIotProductClassify(iotDeviceRespVO.getAssetClass());
            iotDeviceRespVO.setAssetClassName(iotProductClassify.getName());
        }

        return success(result);
    }


    @GetMapping("/td/test")
    @Operation(summary = "获得设备台账包含数采信息")
    @PermitAll
    public void getIotDeviceTdePage() {
        List<YfDeviceDO> allDevice = yfDeviceService.getAllDevice();
        System.out.println(allDevice);
    }

    @GetMapping("/deviceAssociateBomPage")
    @Operation(summary = "获得设备台账分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> deviceAssociateBomPage(@Valid IotDevicePageReqVO pageReqVO) {
        PageResult<IotDeviceRespVO> pageResult = iotDeviceService.deviceAssociateBomPage(pageReqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(pageResult.getList(), IotDeviceRespVO::getDeptId));
        // 拼接BOM节点信息
        return success(new PageResult<>(IotDeviceConvert.INSTANCE.convertList1(pageResult.getList(), deptMap), pageResult.getTotal()));
    }

    @GetMapping("/deviceAssociateBomList")
    @Operation(summary = "获得设备-bom关联关系列表")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<List<IotDeviceRespVO>> deviceAssociateBomList(IotDevicePageReqVO pageReqVO) {
        List<IotDeviceRespVO> devices = iotDeviceService.deviceAssociateBomList(pageReqVO);
        if (CollUtil.isEmpty(devices)) {
            return success(new ArrayList<>());
        }
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(devices, IotDeviceRespVO::getDeptId));
        return success(IotDeviceConvert.INSTANCE.convertList1(devices, deptMap));
    }

    @GetMapping("/deviceAssociateBomListPage")
    @Operation(summary = "获得设备-bom关联关系列表")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:query')")
    public CommonResult<PageResult<IotDeviceRespVO>> deviceAssociateBomListPage(IotDevicePageReqVO pageReqVO) {
        PageResult<IotDeviceRespVO> devices = iotDeviceService.deviceAssociateBomListPage(pageReqVO);
        if (CollUtil.isEmpty(devices.getList())) {
            return success(new PageResult<>(devices.getTotal()));
        }
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(devices.getList(), IotDeviceRespVO::getDeptId));
        return success(new PageResult<>(IotDeviceConvert.INSTANCE.convertList1(devices.getList(), deptMap), devices.getTotal()));
    }

    /**
     * 设备动态分布 设置关联查询信息
     * @param devices
     * @return
     */
    private List<IotDeviceRespVO> buildDeviceDynamicsList(List<IotDeviceDO> devices) {
        if (CollUtil.isEmpty(devices)) {
            return Collections.emptyList();
        }
        // 设备部门信息
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(devices, IotDeviceDO::getDeptId));
        // 查询设备关联的 负责人
        Map<Long, String> devicePersonNames = iotDevicePersonService.getIotDevicePerson(convertList(devices, IotDeviceDO::getId));
        // 2. 拼接数据
        return BeanUtils.toBean(devices, IotDeviceRespVO.class, (deviceVO) -> {
            // 2.1 拼接部门信息
            findAndThen(deptMap, deviceVO.getDeptId(), dept -> deviceVO.setDeptName(dept.getName()));
            // 2.2 设备关联的负责人姓名
            findAndThen(devicePersonNames, deviceVO.getId(), person -> deviceVO.setResponsibleNames(person));
        });
    }

    private List<IotDeviceSimpleRespVO> buildDeviceSimpleListNoPermission(List<IotDeviceDO> devices) {
        if (CollUtil.isEmpty(devices)) {
            return Collections.emptyList();
        }
        AtomicReference<Map<Long, DeptDO>> deptMap = new AtomicReference<>(new HashMap<>());
        AtomicReference<Map<Long, String>> devicePersonNames = new AtomicReference<>(new HashMap<>());
        DataPermissionUtils.executeIgnore(() -> {
            // 设备部门信息
            deptMap.set(deptService.getDeptMap(
                    convertList(devices, IotDeviceDO::getDeptId)));
            // 查询设备关联的 负责人
            devicePersonNames.set(iotDevicePersonService.getIotDevicePerson(convertList(devices, IotDeviceDO::getId)));
        });
        // 2. 拼接数据
        return BeanUtils.toBean(devices, IotDeviceSimpleRespVO.class, (deviceVO) -> {
            IotDeviceStatusEnum statusEnum = IotDeviceStatusEnum.nameOf(deviceVO.getDeviceStatus());
            deviceVO.setDeviceStatusName(ObjUtil.isNotEmpty(statusEnum) ? statusEnum.getMsg() : "-");
            // 2.1 拼接部门信息
            findAndThen(deptMap.get(), deviceVO.getDeptId(), dept -> deviceVO.setDeptName(dept.getName()));
            // 2.2 设备关联的负责人姓名
            findAndThen(devicePersonNames.get(), deviceVO.getId(), person -> deviceVO.setDevicePersons(person));
        });
    }

    private List<IotDeviceSimpleRespVO> buildDeviceSimpleList(List<IotDeviceDO> devices) {
        if (CollUtil.isEmpty(devices)) {
            return Collections.emptyList();
        }
        // 设备部门信息
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(devices, IotDeviceDO::getDeptId));
        // 查询设备关联的 负责人
        Map<Long, String> devicePersonNames = iotDevicePersonService.getIotDevicePerson(convertList(devices, IotDeviceDO::getId));
        // 2. 拼接数据
        return BeanUtils.toBean(devices, IotDeviceSimpleRespVO.class, (deviceVO) -> {
            IotDeviceStatusEnum statusEnum = IotDeviceStatusEnum.nameOf(deviceVO.getDeviceStatus());
            deviceVO.setDeviceStatusName(ObjUtil.isNotEmpty(statusEnum) ? statusEnum.getMsg() : "-");
            // 2.1 拼接部门信息
            findAndThen(deptMap, deviceVO.getDeptId(), dept -> deviceVO.setDeptName(dept.getName()));
            // 2.2 设备关联的负责人姓名
            findAndThen(devicePersonNames, deviceVO.getId(), person -> deviceVO.setDevicePersons(person));
        });
    }

    /**
     * 组装 设备-bom 关联关系对象
     * @param devices
     * @return
     */
    private List<IotDeviceRespVO> buildDevicePersonsList(List<IotDeviceRespVO> devices) {
        if (CollUtil.isEmpty(devices)) {
            return Collections.emptyList();
        }
        // 设备部门信息
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(devices, IotDeviceRespVO::getDeptId));
        // 查询设备关联的 负责人
        Map<Long, String> devicePersonNames = iotDevicePersonService.getIotDevicePerson(convertList(devices, IotDeviceRespVO::getId));
        // 2. 拼接数据
        return BeanUtils.toBean(devices, IotDeviceRespVO.class, (deviceVO) -> {
            // 2.1 拼接部门信息
            findAndThen(deptMap, deviceVO.getDeptId(), dept -> deviceVO.setDeptName(dept.getName()));
            // 2.2 设备关联的负责人姓名
            findAndThen(devicePersonNames, deviceVO.getId(), person -> deviceVO.setResponsibleNames(person));
        });
    }

    /**
     * 组装 设备-bom 关联关系对象
     * @param devices
     * @return
     */
    private List<IotDeviceRespVO> buildDeviceStatusList(List<IotDeviceRespVO> devices) {
        if (CollUtil.isEmpty(devices)) {
            return Collections.emptyList();
        }
        // 设备部门信息
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(devices, IotDeviceRespVO::getDeptId));
        // 2. 拼接数据
        return BeanUtils.toBean(devices, IotDeviceRespVO.class, (deviceVO) -> {
            // 2.1 拼接部门信息
            findAndThen(deptMap, deviceVO.getDeptId(), dept -> deviceVO.setDeptName(dept.getName()));
        });
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出设备台账 Excel")
    @PreAuthorize("@ss.hasPermission('rq:iot-device:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportIotDeviceExcel(@Valid IotDevicePageReqVO pageReqVO,@Valid SortablePageParam pageParam,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        Set<Long> ids;
        if (Objects.isNull(pageReqVO.getDeptId())){
            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
            String companyCode = deptUtil.getCompanyCode(loginUserDeptId);
            ids = deptUtil.getDeptIds(companyCode);
            ids.add(pageReqVO.getDeptId());
        } else {
            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
            ids.add(pageReqVO.getDeptId());
        }
        pageReqVO.setDeptIds(new ArrayList<>(ids));
        List<IotDeviceDO> list = iotDeviceService.getAllDevices(pageReqVO);
        List<IotDeviceRespVO> bean = BeanUtils.toBean(list, IotDeviceRespVO.class);
        List<DictDataDO> pmsDeviceStatus = dictDataService.getDictDataListByDictType("pms_device_status");
        bean.forEach(e ->{
            DeptRespDTO dept = deptApi.getDept(e.getDeptId());
            if (dept != null) {
                e.setDeptName(dept.getName());
            }
            pmsDeviceStatus.stream().filter(f -> f.getValue().equals(e.getDeviceStatus())).findFirst().ifPresent(f -> {
                e.setDeviceStatus(f.getLabel());
            });
        });
        // 导出 Excel
        ExcelUtils.write(response, "设备台账.xls", "数据", IotDeviceRespVO.class, bean);
    }

    @GetMapping("/map")
    @Operation(summary = "查询地图设备")
    public CommonResult<List<IotDeviceDO>> getMap(@Valid IotDevicePageReqVO pageReqVO){
        if ("ly".equals(pageReqVO.getSource())){
            //获取数采yf里面的设备
            DevicePageReqVO devicePageReqVO = new DevicePageReqVO();
            devicePageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
            //连油设备
            devicePageReqVO.setProductId(649L);
            List<String> codes = yfDeviceService.getDevicePage(devicePageReqVO).getList().stream().map(YfDeviceDO::getSerialNumber).collect(Collectors.toList());
            List<IotDeviceDO> iotDeviceDOS;
            Long deptId = null;
            if (Objects.isNull(pageReqVO.getDeptId())) {
                deptId = SecurityFrameworkUtils.getLoginUserDeptId();
            }else {
                deptId = pageReqVO.getDeptId();
            }
            Set<Long> ids;
            ids = deptService.getChildDeptIdListFromCache(deptId);
            ids.add(deptId);
            IotDevicePageReqVO reqVO = new IotDevicePageReqVO();
            reqVO.setDeptIds(new ArrayList<>(ids));
            List<IotDeviceDO> devicesByDepts = iotDeviceService.getDevicesByDepts(reqVO);
            iotDeviceDOS = devicesByDepts.stream().filter(e -> codes.contains(e.getDeviceCode())).collect(Collectors.toList());
            return success(iotDeviceDOS);
        } else{
            List<IotDeviceDO> mapDevice = iotDeviceService.getMapDevice(pageReqVO);
            List<IotDeviceDO> collect = mapDevice.stream().filter(e -> Objects.nonNull(e.getLng()) && Objects.nonNull(e.getLat())).collect(Collectors.toList());
            return success(collect);
        }


    }

    @PermitAll
    @GetMapping("/init")
    public void init() {
        iotDeviceService.updateSort();
    }

    @PermitAll
    @GetMapping("/init/brand")
    public void initBrandName() {
        iotDeviceService.updateBrandName();
    }

    @PermitAll
    @GetMapping("/init/charge")
    public void initCharge() {
        iotDeviceService.updateCharge();
    }

    @Autowired
    private OaFlow oaFlow;

    @PermitAll
    @GetMapping("/oa/register")
    public void oaRegister() {
        try {
            oaFlow.getCompany();
//            oaFlow.getDepart();
//            oaFlow.getPerson();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @PermitAll
    @PostMapping("/import")
    @Operation(summary = "导入设备")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
    })
    public void importExcel(@RequestParam("file") MultipartFile file) throws Exception {
        List<DeviceImportExcelVO> list = ExcelUtils.read(file, DeviceImportExcelVO.class);
        iotDeviceService.importDevice(list);
    }

    @Operation(summary = "根据部门id获取设备列表")
    @GetMapping("/dept/{id}")
    public CommonResult<List<ImmutableMap<String, ? extends Serializable>>> findDeviceByDept(@PathVariable Long id) {
        IotDevicePageReqVO iotDevicePageReqVO = new IotDevicePageReqVO();
        iotDevicePageReqVO.setDeptId(id);
        List<IotDeviceDO> allDevices = iotDeviceService.getAllDevices(iotDevicePageReqVO);
        List<ImmutableMap<String, ? extends Serializable>> collect = allDevices.stream().map(e -> ImmutableMap.of("id", e.getId(), "deviceName", e.getDeviceName(), "deviceCode", e.getDeviceCode())).collect(Collectors.toList());
        return success(collect);
    }

    @Operation(summary = "获取延凡token")
    @GetMapping("/yf/token")
    public CommonResult<String> getYfToken() {
        Map<String, Object> map = new HashMap<>();
//        map.put("code", "12");
        map.put("password", "123456");
        map.put("sourceType", 1);
        map.put("username", "yanfan");
//        map.put("uuid", "5dc9dd7f2337451f8f708131166eabab");
        JSONObject entries = restTemplate.postForObject("http://172.21.10.65/prod-api/login", map, JSONObject.class);
        if (Objects.nonNull(entries)) {
            if (Objects.nonNull(entries.get("token"))) {
                return success(String.valueOf(entries.get("token")));
            }
        }
        return success("");
    }
}
