package cn.iocoder.yudao.module.iot.controller.admin.device;

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.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.infra.service.job.JobService;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*;
import cn.iocoder.yudao.module.iot.controller.admin.devicecontactmodel.vo.DeviceContactModelPageReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceAttributeDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicecontactmodel.DeviceContactModelDO;
import cn.iocoder.yudao.module.iot.framework.mqtt.consumer.IMqttservice;
import cn.iocoder.yudao.module.iot.service.device.DeviceService;
import cn.iocoder.yudao.module.iot.service.device.TDengineService;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.quartz.SchedulerException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
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;

@Tag(name = "管理后台 - 物联设备")
@RestController
@RequestMapping("/iot/device")
@Validated
public class DeviceController {

    @Resource
    private DeviceService deviceService;
    @Resource
    private TDengineService tDengineService;
    @Resource
    private JobService jobService;

//    @Resource
//    private OpcUaSubscriptionService  opcUaService;

//    @Resource
//    private IMqttservice mqttService;


    @PostMapping("/create")
    @Operation(summary = "创建物联设备")
    @PreAuthorize("@ss.hasPermission('iot:device:create')")
    public CommonResult<DeviceDO> createDevice(@Valid @RequestBody DeviceSaveReqVO createReqVO) throws SchedulerException {
        DeviceDO device = deviceService.createDevice(createReqVO);
        //初始化Td表
//        tDengineService.initDatabaseAndTable(device.getId());

        return success(device);
    }

    @PutMapping("/update")
    @Operation(summary = "更新物联设备")
    @PreAuthorize("@ss.hasPermission('iot:device:update')")
    public CommonResult<Boolean> updateDevice(@Valid @RequestBody DeviceSaveReqVO updateReqVO) {
        deviceService.updateDevice(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除物联设备")
    @Parameter(name = "ids", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('iot:device:delete')")
    public CommonResult<Boolean> deleteDevice(@RequestParam("ids") String ids) {
        // 将逗号分隔的字符串转换为Long类型的List
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(String::trim) // 去除可能存在的空格
                .map(Long::valueOf)
                .collect(Collectors.toList());

        deviceService.deleteDevice(idList);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得物联设备")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('iot:device:query')")
    public CommonResult<DeviceRespVO> getDevice(@RequestParam("id") Long id) {
        DeviceRespVO deviceRespVO = deviceService.getDevice(id);
        return success(deviceRespVO);
    }

    @GetMapping("/page")
    @Operation(summary = "获得物联设备分页")
    @PreAuthorize("@ss.hasPermission('iot:device:query')")
    public CommonResult<PageResult<DeviceRespVO>> getDevicePage(@Valid DevicePageReqVO pageReqVO) {
        PageResult<DeviceRespVO> pageResult = deviceService.getDevicePage(pageReqVO);
        return success(pageResult);
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出物联设备 Excel")
    @PreAuthorize("@ss.hasPermission('iot:device:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportDeviceExcel(@Valid DevicePageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        List<DeviceRespVO> list = deviceService.getDevicePage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "物联设备.xls", "数据", DeviceRespVO.class,list);
    }
    @GetMapping("/deviceList")
    @PreAuthorize("@ss.hasPermission('iot:device:query')")
    public CommonResult<List<DeviceRespVO>> deviceList(@Valid DevicePageReqVO pageReqVO) {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<DeviceRespVO> list = deviceService.getDevicePage(pageReqVO).getList();
        return success(list);
    }

    @GetMapping("/noUsedlist")
    @Operation(summary = "获得未关联设备台账列表")
    @PreAuthorize("@ss.hasPermission('mes:device-ledger:query')")
    public CommonResult<List<DeviceRespVO>> getDeviceLedgerListByNoUsed() {
        DevicePageReqVO pageReqVO = new DevicePageReqVO();
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<DeviceRespVO> list = deviceService.getDevicePage(pageReqVO).getList();
        List<Long> ids = deviceService.deviceLedgerList();
        List<DeviceRespVO> filteredList = list.stream()
                .filter(device -> !ids.contains(device.getId()))
                .collect(Collectors.toList());
        return success(filteredList);
    }

    @GetMapping("/noUsedlist2")
    @Operation(summary = "获得未关联设备台账列表")
    @PreAuthorize("@ss.hasPermission('mes:device-ledger:query')")
    public CommonResult<List<DeviceRespVO>> getDeviceLedgerList2ByNoUsed(@RequestParam("id") Long id) {
        DevicePageReqVO pageReqVO = new DevicePageReqVO();
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<DeviceRespVO> list = deviceService.getDevicePage(pageReqVO).getList();
        List<Long> ids = deviceService.deviceLedgerList();

        List<DeviceRespVO> filteredList = list.stream()
                .filter(device -> {
                    if (id != null && id.equals(device.getId())) {
                        return true;
                    }
                    return !ids.contains(device.getId());
                })
                .collect(Collectors.toList());
        return success(filteredList);
    }

    @PostMapping("/connect")
    @Operation(summary = "连接")
//    @PreAuthorize("@ss.hasPermission('iot:device:create')")
    public CommonResult<Boolean> connectDevice(@RequestBody DeviceSaveReqVO createReqVO) throws SchedulerException {

        deviceService.connectDevice(createReqVO);

        //开启或停止定时任务
//        JobDO jobDO = jobService.getJobByDeviceId(createReqVO.getId());
//        jobService.updateJobStatus(jobDO.getId(), createReqVO.getIsConnect());

        return success(Boolean.TRUE);
    }


    @PostMapping("/copy")
    @Operation(summary = "复制设备")
//    @PreAuthorize("@ss.hasPermission('iot:device-model:create')")
    public CommonResult<Long> copyDevice(@RequestParam("id") Long id) {
        return success(deviceService.copyDevice(id));
    }


    @GetMapping("/lineDevicePage")
    @Operation(summary = "获得产线设备分页")
    @PreAuthorize("@ss.hasPermission('iot:device:query')")
    public CommonResult<PageResult<LineDeviceRespVO>> lineDevicePage(@Valid LineDeviceRequestVO pageReqVO) {
        PageResult<LineDeviceRespVO> pageResult = deviceService.lineDevicePage(pageReqVO);
        return success(pageResult);
    }

    @GetMapping("/export-line-device")
    @Operation(summary = "导出产线设备分页 Excel")
    @PreAuthorize("@ss.hasPermission('iot:device:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportLineDevice(@Valid LineDeviceRequestVO pageReqVO,
                                  HttpServletResponse response) throws IOException {
        List<LineDeviceRespVO> lineDeviceList = deviceService.lineDeviceList(pageReqVO);
        // 设置响应头
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        response.setHeader("Content-Disposition",
                "attachment;filename=" + URLEncoder.encode("设备运行报表记录.xls", "UTF-8"));
        response.setHeader("Content-Encoding", "identity");
        // 导出Excel
        String fileName = String.format("数据实时监控_%s.xls", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));

        // 导出 Excel
        ExcelUtils.write(response, fileName, "数据", LineDeviceRespVO.class,lineDeviceList);
    }


    @GetMapping("/singleDevice")
    @Operation(summary = "单设备查看")
//    @PreAuthorize("@ss.hasPermission('iot:device:query')")
    public CommonResult<Map<String, List<Map<String, Object>>>> singleDevice(@RequestParam("deviceId") Long deviceId) throws JsonProcessingException {
        Map<String, List<Map<String, Object>>> deviceContactModelDO=deviceService.singleDevice(deviceId);
        return success(deviceContactModelDO);
    }


    @GetMapping("/historyRecord")
    @Operation(summary = "历史记录查询")
//    @PreAuthorize("@ss.hasPermission('iot:device:query')")
    public CommonResult<PageResult<Map<String, Object>>> historyRecord(@RequestParam("deviceId") Long deviceId,
                                                                 @RequestParam(name = "collectionStartTime", required = false) String collectionStartTime,
                                                                 @RequestParam(name = "collectionEndTime", required = false) String collectionEndTime,
                                                                 @RequestParam(name = "pageNo", required = false, defaultValue = "1") Integer page,
                                                                  @RequestParam(name = "pageSize", required = false, defaultValue = "10") Integer pageSize
                                                                 ) throws JsonProcessingException {
        PageResult<Map<String, Object>> deviceContactModelDO=deviceService.historyRecord(deviceId,collectionStartTime,collectionEndTime,page,pageSize);
        return success(deviceContactModelDO);
    }


    @GetMapping("/getDeviceOperationalStatus")
    @Operation(summary = "获取首页设备运行状态")
    @PreAuthorize("@ss.hasPermission('iot:device:query')")
    @Parameter(name = "orgId", description = "产线组织Id")
    public CommonResult<DeviceOperationStatusRespVO> getDeviceOperationalStatus(@RequestParam(name = "orgId",required = false) Long orgId) throws JsonProcessingException {
        DeviceOperationStatusRespVO deviceOperationalStatus=deviceService.getDeviceOperationalStatus();
        return success(deviceOperationalStatus);
    }


    // ==================== 子表（设备属性） ====================

    @GetMapping("/device-attribute/page")
    @Operation(summary = "获得设备属性分页")
    @Parameter(name = "deviceId", description = "设备id")
    @PreAuthorize("@ss.hasPermission('iot:device:query')")
    public CommonResult<PageResult<DeviceContactModelDO>> getDeviceAttributePage(PageParam pageParam, DeviceContactModelPageReqVO deviceModelAttributePageReqVO) {
        return success(deviceService.getDeviceAttributePage(pageParam, deviceModelAttributePageReqVO));
    }


    @GetMapping("/device-attribute/list")
    @Operation(summary = "获得设备属性列表")
    @Parameter(name = "deviceId", description = "设备id")
    @PreAuthorize("@ss.hasPermission('iot:device:query')")
    public CommonResult<List<DeviceContactModelDO>> getDeviceAttributeList(@RequestParam(name = "deviceId") Long deviceId) {
        return success(deviceService.getDeviceAttributeList(deviceId));
    }


    @PostMapping("/device-attribute/create")
    @Operation(summary = "创建设备属性")
    @PreAuthorize("@ss.hasPermission('iot:device:create')")
    public CommonResult<Long> createDeviceAttribute(@Valid @RequestBody DeviceAttributeDO deviceAttribute) {
        return success(deviceService.createDeviceAttribute(deviceAttribute));
    }

    @PutMapping("/device-attribute/update")
    @Operation(summary = "更新设备属性")
    @PreAuthorize("@ss.hasPermission('iot:device:update')")
    public CommonResult<Boolean> updateDeviceAttribute(@Valid @RequestBody DeviceAttributeDO deviceAttribute) {
        deviceService.updateDeviceAttribute(deviceAttribute);
        return success(true);
    }

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

	@GetMapping("/device-attribute/get")
	@Operation(summary = "获得设备属性")
	@Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('iot:device:query')")
	public CommonResult<DeviceAttributeDO> getDeviceAttribute(@RequestParam("id") Long id) {
	    return success(deviceService.getDeviceAttribute(id));
	}

    @GetMapping("/devicePointList")
    @PreAuthorize("@ss.hasPermission('iot:device:query')")
    public CommonResult<List<DevicePointRespVO>> devicePointList() {
        return success( deviceService.devicePointList());
    }


    @PostMapping("/scheduledStart")
    public CommonResult<Boolean> scheduledStart(@RequestParam("id") Long id) {
        return success(deviceService.scheduledStart(id));
    }


    @PostMapping("/scheduledStop")
    public CommonResult<Boolean> scheduledStop(@RequestParam("id") Long id) {
        return success(deviceService.scheduledStop(id));
    }

    @GetMapping("/device-attribute/batchList")
    @Operation(summary = "获得多个设备的属性数据")
    @Parameter(name = "goviewId", description = "大屏ID", required = true)
    @PreAuthorize("@ss.hasPermission('iot:device:query')")
    public CommonResult<List<Map<String, Object>>> getMultiDeviceAttributes(@RequestParam("goviewId") Long goviewId) {
        return success(deviceService.getMultiDeviceAttributes(goviewId));
    }


//    @PostMapping("/subscribe")
//    public String subscribeTopic(@RequestParam String topic) {
//        try {
//            int result = mqttService.subscribeTopic(topic); // 使用服务层安全订阅
//            if (result >0 ) {
//                return "订阅成功: " + topic;
//            } else {
//                return "订阅失败: " + topic;
//            }
//        } catch (MqttException e) {
//            return "订阅异常: " + e.getMessage();
//        }
//    }

    @PutMapping("/update-enabled")
    @Operation(summary = "更新任务管理启用状态")
    @PreAuthorize("@ss.hasPermission('mes:task-management:update')")
    public CommonResult<Boolean> updateDeviceEnabled(@Valid @RequestBody DeviceUpdateEnabledReqVO updateEnabledReqVO) throws MqttException {
        deviceService.updateDeviceEnabled(updateEnabledReqVO);
        return success(true);
    }

}