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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
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.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.pms.ThingsModelDTO;
import cn.iocoder.yudao.module.pms.controller.admin.TableDataInfo;
import cn.iocoder.yudao.module.pms.controller.admin.iotwebtopoproject.vo.*;
import cn.iocoder.yudao.module.pms.controller.admin.iotwebtopoprojectdevice.vo.IotWebtopoProjectDevicePageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotwebtopoproject.IotWebtopoProjectDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotwebtopoprojectdevice.IotWebtopoProjectDeviceDO;
import cn.iocoder.yudao.module.pms.service.IotDeviceService;
import cn.iocoder.yudao.module.pms.service.iotwebtopoproject.IotWebtopoProjectService;
import cn.iocoder.yudao.module.pms.service.iotwebtopoprojectdevice.IotWebtopoProjectDeviceService;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.*;

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.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;

@Tag(name = "管理后台 - 组态项目列")
@RestController
@RequestMapping("/pms/iot-webtopo-project")
@Validated
public class IotWebtopoProjectController {

    @Resource
    private IotWebtopoProjectService iotWebtopoProjectService;

    @Resource
    private IotWebtopoProjectDeviceService iotWebtopoProjectDeviceService;

    @Resource
    private IotDeviceService iotDeviceService;

    @Value("${yanfan.url}")
    private String yanfanUrl;

    @Resource
    private RestTemplate restTemplate;

    @PostMapping("/create")
    @Operation(summary = "创建组态项目列")
    @PreAuthorize("@ss.hasPermission('pms:iot-webtopo-project:create')")
    public CommonResult<Long> createIotWebtopoProject(@Valid @RequestBody IotWebtopoProjectSaveReqVO createReqVO) {
        return success(iotWebtopoProjectService.createIotWebtopoProject(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新组态项目列")
    @PreAuthorize("@ss.hasPermission('pms:iot-webtopo-project:update')")
    public CommonResult<Boolean> updateIotWebtopoProject(@Valid @RequestBody IotWebtopoProjectSaveReqVO updateReqVO) {
        iotWebtopoProjectService.updateIotWebtopoProject(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除组态项目列")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('pms:iot-webtopo-project:delete')")
    public CommonResult<Boolean> deleteIotWebtopoProject(@RequestParam("id") Long id) {
        iotWebtopoProjectService.deleteIotWebtopoProject(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得组态项目详情")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('pms:iot-webtopo-project:query')")
    public CommonResult<IotWebtopoProjectRespVO> getIotWebtopoProject(@RequestParam("id") Long id) {
        IotWebtopoProjectDO iotWebtopoProject = iotWebtopoProjectService.getIotWebtopoProject(id);
        return success(buildWebtopProject(iotWebtopoProject));
    }

    @PostMapping("/copyProject")
    @Operation(summary = "复制组态项目")
    @Parameter(name = "id", description = "组态项目id", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('pms:iot-webtopo-project:create')")
    public CommonResult<Long> copyProject(@Valid @RequestBody IotWebtopoProjectSaveReqVO createReqVO) {
        Long newProjectId = iotWebtopoProjectService.copyProject(createReqVO);
        return success(newProjectId);
    }

    /**
     * 查询对应的 组态项目信息
     * @param project
     * @return
     */
    private IotWebtopoProjectRespVO buildWebtopProject(IotWebtopoProjectDO project) {
        if (ObjUtil.isEmpty(project)) {
            return new IotWebtopoProjectRespVO();
        }
        IotWebtopoProjectRespVO projectVO = BeanUtils.toBean(project, IotWebtopoProjectRespVO.class);
        // 查询组态项目对应的设备列表
        IotWebtopoProjectDevicePageReqVO pageReqVO = new IotWebtopoProjectDevicePageReqVO();
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        pageReqVO.setProjectId(project.getId());
        PageResult<IotWebtopoProjectDeviceDO> pageDevices = iotWebtopoProjectDeviceService.getIotWebtopoProjectDevicePage(pageReqVO);
        if (ObjUtil.isNotEmpty(pageDevices)) {
            List<IotWebtopoProjectDeviceDO> projectDevices = pageDevices.getList();
            List<IotWebtopoDeviceRespVO> devices = new ArrayList<>();
            Set<Long> deviceIds = new HashSet<>();
            if (CollUtil.isNotEmpty(projectDevices)) {
                projectDevices.forEach(pd -> {
                    deviceIds.add(pd.getDeviceId());
                });
                // 批量查询所有设备详情
                if (CollUtil.isNotEmpty(deviceIds)) {
                    // todo 查询IOT平台获取每个设备的所有 点位参数 列表
                    Map<Long, IotDeviceRespVO> devicePair = iotDeviceService.getDeviceMap(new ArrayList<>(deviceIds));
                    if (CollUtil.isNotEmpty(devicePair)) {
                        devicePair.forEach((deviceId, device) -> {
                            // 查询包含 yanfan 数采设备id 的设备
                            Long yfDeviceId = device.getYfDeviceId();
                            List<IotWebtopoDevicePointParamsRespVO> params = new ArrayList<>();
                            if (ObjUtil.isNotEmpty(yfDeviceId)) {
                                TableDataInfo tableDataInfo = restTemplate.getForObject(yanfanUrl + "/prod-api/iot/device/listThingsModel?deviceId=" + yfDeviceId + "&pageNum=1&pageSize=200", TableDataInfo.class);
                                if (ObjUtil.isNotEmpty(tableDataInfo)) {
                                    List<ThingsModelDTO> thingsModel = JSON.parseArray(JSON.toJSONString(tableDataInfo.getRows()), ThingsModelDTO.class);
                                    if (CollUtil.isNotEmpty(thingsModel)) {
                                        thingsModel.forEach(model -> {
                                            IotWebtopoDevicePointParamsRespVO tempParam = new IotWebtopoDevicePointParamsRespVO();
                                            tempParam.setParamCode(model.getIdentifier());
                                            tempParam.setParamName(model.getModelName());
                                            tempParam.setParamUnit(model.getUnit());
                                            params.add(tempParam);
                                        });
                                    }
                                }
                            }
                            IotWebtopoDeviceRespVO tempDevice = new IotWebtopoDeviceRespVO();
                            tempDevice.setId(device.getId());
                            tempDevice.setDeviceName(device.getDeviceName());
                            tempDevice.setDeviceCode(device.getDeviceCode());
                            tempDevice.setPointParams(params);
                            devices.add(tempDevice);
                        });
                        projectVO.setLinkedDevices(devices);
                    }
                }
            }
        }
        return projectVO;
    }

    @GetMapping("/page")
    @Operation(summary = "获得组态项目列分页")
    @PreAuthorize("@ss.hasPermission('pms:iot-webtopo-project:query')")
    public CommonResult<PageResult<IotWebtopoProjectRespVO>> getIotWebtopoProjectPage(@Valid IotWebtopoProjectPageReqVO pageReqVO) {
        PageResult<IotWebtopoProjectDO> pageResult = iotWebtopoProjectService.getIotWebtopoProjectPage(pageReqVO);
        return success(new PageResult<>(buildWebtopProjects(pageResult.getList(), pageReqVO), pageResult.getTotal()));
        // return success(BeanUtils.toBean(pageResult, IotWebtopoProjectRespVO.class));
    }

    /**
     * 查询对应的 组态项目信息 列表 绑定的设备列表
     * @param projects
     * @return
     */
    private List<IotWebtopoProjectRespVO> buildWebtopProjects(List<IotWebtopoProjectDO> projects, IotWebtopoProjectPageReqVO reqVO) {
        if (CollUtil.isEmpty(projects)) {
            return Collections.emptyList();
        }
        Set<Long> projectIds = convertSet(projects, IotWebtopoProjectDO::getId);
        if (CollUtil.isEmpty(projectIds)) {
            return Collections.emptyList();
        }
        Map<Long, List<IotWebtopoProjectDeviceDO>> projectDevicesPair = new HashMap<>();
        // key组态项目id   value项目项目关联的设备id集合
        Map<Long, List<Long>> projectDeviceIdPair = new HashMap<>();
        // 查询组态项目对应的设备列表
        IotWebtopoProjectDevicePageReqVO pageReqVO = new IotWebtopoProjectDevicePageReqVO();
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        pageReqVO.setProjectIds(projectIds);
        PageResult<IotWebtopoProjectDeviceDO> pageDevices = iotWebtopoProjectDeviceService.getIotWebtopoProjectDevicePage(pageReqVO);
        if (ObjUtil.isNotEmpty(pageDevices)) {
            List<IotWebtopoProjectDeviceDO> projectDevices = pageDevices.getList();
            List<IotWebtopoDeviceRespVO> devices = new ArrayList<>();
            Set<Long> deviceIds = new HashSet<>();
            if (CollUtil.isNotEmpty(projectDevices)) {
                projectDevices.forEach(pd -> {
                    deviceIds.add(pd.getDeviceId());
                    if (projectDeviceIdPair.containsKey(pd.getProjectId())) {
                        List<Long> tempDeviceIds = projectDeviceIdPair.get(pd.getProjectId());
                        tempDeviceIds.add(pd.getDeviceId());
                        projectDeviceIdPair.put(pd.getProjectId(), tempDeviceIds);
                    } else {
                        List<Long> tempDeviceIds = new ArrayList<>();
                        tempDeviceIds.add(pd.getDeviceId());
                        projectDeviceIdPair.put(pd.getProjectId(), tempDeviceIds);
                    }
                });

            }
        }
        return BeanUtils.toBean(projects, IotWebtopoProjectRespVO.class, (projectVO) -> {
            // 组态项目绑定的设备id列表
            findAndThen(projectDeviceIdPair, projectVO.getId(), deviceIds -> projectVO.setLinkedDeviceIds(deviceIds));
        });
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出组态项目列 Excel")
    @PreAuthorize("@ss.hasPermission('pms:iot-webtopo-project:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportIotWebtopoProjectExcel(@Valid IotWebtopoProjectPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<IotWebtopoProjectDO> list = iotWebtopoProjectService.getIotWebtopoProjectPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "组态项目列.xls", "数据", IotWebtopoProjectRespVO.class,
                        BeanUtils.toBean(list, IotWebtopoProjectRespVO.class));
    }

}