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

import cn.iocoder.yudao.framework.common.util.opc.OpcUtils;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.DeviceRespVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicecontactmodel.DeviceContactModelDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.recipe.RecipeDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.recipeplandetail.RecipePlanDetailDO;
import cn.iocoder.yudao.module.iot.service.device.DeviceService;
import cn.iocoder.yudao.module.iot.service.devicecontactmodel.DeviceContactModelService;
import cn.iocoder.yudao.module.iot.service.recipe.RecipeService;
import cn.iocoder.yudao.module.iot.service.recipeplandetail.RecipePlanDetailService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;

import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import java.util.function.Function;
import java.util.stream.Collectors;

import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;

import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_NOT_EXISTS;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.RECIPE_NOT_EXISTS;

import cn.iocoder.yudao.module.iot.controller.admin.recipedevicerecord.vo.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.recipedevicerecord.RecipeDeviceRecordDO;
import cn.iocoder.yudao.module.iot.service.recipedevicerecord.RecipeDeviceRecordService;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;


// 新增必要的导入
import cn.iocoder.yudao.module.iot.service.recipedeviceattribute.RecipeDeviceAttributeService;
import cn.iocoder.yudao.module.iot.service.device.TDengineService;
import cn.iocoder.yudao.module.iot.dal.dataobject.recipedeviceattribute.RecipeDeviceAttributeDO;
import cn.iocoder.yudao.module.iot.service.recipepoint.RecipePointService;
import cn.iocoder.yudao.module.iot.service.recipepointrecord.RecipePointRecordService;

@Tag(name = "管理后台 - 设备点位采集值记录")
@RestController
@RequestMapping("/iot/recipe-device-record")
@Validated
public class RecipeDeviceRecordController {

    @Resource
    private RecipeDeviceRecordService recipeDeviceRecordService;
    // 新增注入的服务
    @Resource
    private RecipeDeviceAttributeService recipeDeviceAttributeService;

    @Resource
    private RecipePlanDetailService recipePlanDetailService;

    @Resource
    private RecipeService recipeService;

    @Resource
    private TDengineService tDengineService;
    @Resource
    private RecipePointService recipePointService;
    @Resource
    private RecipePointRecordService recipePointRecordService;
    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private DeviceService deviceService;

    @Resource
    private DeviceContactModelService deviceContactModelService;



    @PostMapping("/create")
    @Operation(summary = "创建设备点位采集值记录")
    @PreAuthorize("@ss.hasPermission('iot:recipe-device-record:create')")
    public CommonResult<Long> createRecipeDeviceRecord(@Valid @RequestBody RecipeDeviceRecordSaveReqVO createReqVO) {
        return success(recipeDeviceRecordService.createRecipeDeviceRecord(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新设备点位采集值记录")
    @PreAuthorize("@ss.hasPermission('iot:recipe-device-record:update')")
    public CommonResult<Boolean> updateRecipeDeviceRecord(@Valid @RequestBody RecipeDeviceRecordSaveReqVO updateReqVO) {
        recipeDeviceRecordService.updateRecipeDeviceRecord(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除设备点位采集值记录")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('iot:recipe-device-record:delete')")
    public CommonResult<Boolean> deleteRecipeDeviceRecord(@RequestParam("id") Long id) {
        recipeDeviceRecordService.deleteRecipeDeviceRecord(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得设备点位采集值记录")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('iot:recipe-device-record:query')")
    public CommonResult<RecipeDeviceRecordRespVO> getRecipeDeviceRecord(@RequestParam("id") Long id) {
        RecipeDeviceRecordDO recipeDeviceRecord = recipeDeviceRecordService.getRecipeDeviceRecord(id);
        return success(BeanUtils.toBean(recipeDeviceRecord, RecipeDeviceRecordRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得设备点位采集值记录分页")
    @PreAuthorize("@ss.hasPermission('iot:recipe-device-record:query')")
    public CommonResult<PageResult<RecipeDeviceRecordRespVO>> getRecipeDeviceRecordPage(@Valid RecipeDeviceRecordPageReqVO pageReqVO) {
        PageResult<RecipeDeviceRecordDO> pageResult = recipeDeviceRecordService.getRecipeDeviceRecordPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, RecipeDeviceRecordRespVO.class));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出设备点位采集值记录 Excel")
    @PreAuthorize("@ss.hasPermission('iot:recipe-device-record:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportRecipeDeviceRecordExcel(@Valid RecipeDeviceRecordPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<RecipeDeviceRecordDO> list = recipeDeviceRecordService.getRecipeDeviceRecordPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "设备点位采集值记录.xls", "数据", RecipeDeviceRecordRespVO.class,
                        BeanUtils.toBean(list, RecipeDeviceRecordRespVO.class));
    }



    /**
     * 批量创建设备点位采集记录和配方点位记录
     * @return 创建结果
     * @throws JsonProcessingException JSON处理异常
     */
    @PostMapping("/batch-create")
    @Operation(summary = "批量创建设备点位采集记录和配方点位记录")
    @PreAuthorize("@ss.hasPermission('iot:recipe-device-record:create')")
    public CommonResult<Boolean> batchCreateRecipeDeviceRecord(
            @RequestParam("id") Long id) {


        RecipePlanDetailDO recipePlanDetailDO = recipePlanDetailService.getRecipePlanDetail(id);
        Long recipeId = recipePlanDetailDO.getRecipeId();

        // ========== 第一步：查询配方关联的点位属性信息 ==========
        // 1.1 根据recipeId查询iot_recipe_device_attribute表记录

//        recipePlanDetailDO.setRecipeId(recipeId);
        List<RecipeDeviceAttributeDO> attributeList = recipeDeviceAttributeService.getByRecipeId(recipeId);

        //先删除在添加
        List<RecipeDeviceRecordDO> recipeDeviceRecordDOS = recipeDeviceRecordService.getListByRecipeId(recipeId);
        if (!recipeDeviceRecordDOS.isEmpty()){
            recipeDeviceRecordService.deleteByIds(recipeDeviceRecordDOS);
        }
        RecipeDO recipe = recipeService.getRecipe(recipeId);
        if (recipe == null){
            throw exception(RECIPE_NOT_EXISTS);
        }

        DeviceRespVO device = deviceService.getDevice(recipe.getMachineId());
        if (device != null) {
//            throw exception(DEVICE_NOT_EXISTS);


            try {

                Map<Long, DeviceContactModelDO> deviceContactModelMap = new HashMap<>();
                List<DeviceContactModelDO> deviceContactModelDOS = deviceContactModelService.selectListByDeviceId(device.getId());
                if (!deviceContactModelDOS.isEmpty()) {
                    deviceContactModelMap = deviceContactModelDOS.stream()
                            .collect(Collectors.toMap(
                                    DeviceContactModelDO::getId,
                                    Function.identity()
                            ));
                }


//                Map<Long, Map<String, Object>> deviceDataMap = deviceService.createDeviceDataMap(device.getId());//recipeRespVO.getDeviceId()

                Map<String, Object> map = tDengineService.newSelectLatestRow(device.getId());

//            OpcUtils.connect(device.getId(),device.getUrl(),device.getUsername(),device.getPassword(),10);

                for (RecipeDeviceAttributeDO attributeDO : attributeList) {
//                    Map<String, Object> data = deviceDataMap.get(attributeDO.getAttributeId());

                    DeviceContactModelDO deviceContactModelDO = deviceContactModelMap.get(attributeDO.getAttributeId());
                    if (deviceContactModelDO == null) {
                        continue;
                    }
                    // 创建
                    RecipeDeviceRecordDO recipeDeviceRecordDO = new RecipeDeviceRecordDO();
                    recipeDeviceRecordDO.setRecipeId(recipeId);
                    recipeDeviceRecordDO.setAttributeCode(deviceContactModelDO.getAttributeCode());
                    recipeDeviceRecordDO.setAttributeName(deviceContactModelDO.getAttributeName());
                    recipeDeviceRecordDO.setDataType(deviceContactModelDO.getDataType());
                    recipeDeviceRecordDO.setDeviceId(deviceContactModelDO.getDeviceId());
                    recipeDeviceRecordDO.setDataUnit(deviceContactModelDO.getDataUnit());
//                recipeDeviceRecordDO.setValue((String) OpcUtils.readValues(device.getId(),deviceContactModelDO.getAddress()));
//                    if (data.get("addressValue") != null && data.get("addressValue").toString() != null) {
//                        recipeDeviceRecordDO.setValue(data.get("addressValue").toString());
//                    }
                    recipeDeviceRecordDO.setValue(map.get(deviceContactModelDO.getAttributeCode()));

                    recipeDeviceRecordService.createRecipeDeviceRecord(BeanUtils.toBean(recipeDeviceRecordDO, RecipeDeviceRecordSaveReqVO.class));

                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        return success(true);
    }

    // ========== 内部辅助类 ==========
    /**
     * 点位参考值VO
     */
    public static class PointReferVO {
        private Long id; // 配方点位ID
        private String refer; // 参考值

        // getter/setter
        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getRefer() {
            return refer;
        }

        public void setRefer(String refer) {
            this.refer = refer;
        }
    }

    /**
     * 属性信息封装类
     */
    private static class AttributeInfo {
        private Long attributeId; // 属性ID
        private String attributeName; // 属性名
        private String dataUnit; // 数据单位
        private Long deviceId; // 设备ID

        public AttributeInfo(Long attributeId, String attributeName, String dataUnit, Long deviceId) {
            this.attributeId = attributeId;
            this.attributeName = attributeName;
            this.dataUnit = dataUnit;
            this.deviceId = deviceId;
        }

        // getter
        public String getDataUnit() {
            return dataUnit;
        }

        public Long getDeviceId() {
            return deviceId;
        }
    }

}