package cn.iocoder.yudao.module.iot.service.devicemodelattribute;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService;
import cn.iocoder.yudao.module.iot.dal.dataobject.deviceattributetype.DeviceAttributeTypeDO;
import cn.iocoder.yudao.module.iot.dal.mysql.deviceattributetype.DeviceAttributeTypeMapper;
import cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.iot.service.device.TDengineService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.validation.ConstraintViolationException;

import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.iot.controller.admin.devicemodelattribute.vo.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodelattribute.DeviceModelAttributeDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.iot.dal.mysql.devicemodelattribute.DeviceModelAttributeMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;

/**
 * 采集设备模型-点位管理 Service 实现类
 *
 * @author 内蒙必硕
 */
@Service
@Validated
@Slf4j
    public class DeviceModelAttributeServiceImpl implements DeviceModelAttributeService {

    @Resource
    private DeviceModelAttributeMapper deviceModelAttributeMapper;

    @Resource
    private TDengineService tdengineService;

    @Resource
    private DeviceAttributeTypeMapper deviceAttributeTypeMapper;

    @Resource
    private ErpProductUnitService productUnitService;


    @Override
    public Long createDeviceModelAttribute(DeviceModelAttributeSaveReqVO createReqVO) {

        //判断编码是否唯一
        boolean exists = deviceModelAttributeMapper.exists(
                Wrappers.<DeviceModelAttributeDO>lambdaQuery()
                        .eq(DeviceModelAttributeDO::getDeviceModelId, createReqVO.getDeviceModelId())
                        .eq(DeviceModelAttributeDO::getAttributeCode, createReqVO.getAttributeCode()));

        if (exists) {
            throw exception(DEVICE_MODEL_ATTRIBUTE_POTIN_CODE_EXISTS);
        }

                // 插入
        DeviceModelAttributeDO deviceModelAttribute = BeanUtils.toBean(createReqVO, DeviceModelAttributeDO.class);
//        deviceModelAttribute.setTypeName(deviceAttributeTypeMapper.selectById(createReqVO.getAttributeCode()).getName());
        deviceModelAttributeMapper.insert(deviceModelAttribute);
        // 返回
        return deviceModelAttribute.getId();
    }

    @Override
    public void updateDeviceModelAttribute(DeviceModelAttributeSaveReqVO updateReqVO) {
        // 校验存在
        validateDeviceModelAttributeExists(updateReqVO.getId());
        // 更新
        DeviceModelAttributeDO updateObj = BeanUtils.toBean(updateReqVO, DeviceModelAttributeDO.class);
        deviceModelAttributeMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteDeviceModelAttribute(List<Long> idList) {
        for (Long id : idList) {
            // 校验存在
            validateDeviceModelAttributeExists(id);
        }
        // 删除
        deviceModelAttributeMapper.deleteByIds(idList);
    }

    private void validateDeviceModelAttributeExists(Long id) {
        if (deviceModelAttributeMapper.selectById(id) == null) {
            throw exception(DEVICE_MODEL_ATTRIBUTE_NOT_EXISTS);
        }
    }

    @Override
    public DeviceModelAttributeDO getDeviceModelAttribute(Long id) {
        return deviceModelAttributeMapper.selectById(id);
    }

    @Override
    public PageResult<DeviceModelAttributeRespVO> getDeviceModelAttributePage(DeviceModelAttributePageReqVO pageReqVO) {
        //  获取设备模型属性分页数据
        PageResult<DeviceModelAttributeDO> pageResult = deviceModelAttributeMapper.selectPage(pageReqVO);

//        // 获取所有属性类型并构建映射
//        List<DeviceAttributeTypeDO> attributeTypes = deviceAttributeTypeMapper.selectList();
//        Map<Long, String> typeNameMap = attributeTypes.stream()
//                .collect(Collectors.toMap(DeviceAttributeTypeDO::getId, DeviceAttributeTypeDO::getName));
        Map<Long, ErpProductUnitDO> unitMap = productUnitService.getProductUnitMap(
                pageResult.getList().stream()
                        .map(DeviceModelAttributeDO::getDataUnit)
                        .filter(StringUtils::isNotEmpty)
                        .map(str -> {
                            try {
                                return Long.valueOf(str.trim());
                            } catch (NumberFormatException e) {
                                return null;
                            }
                        })
                        .filter(Objects::nonNull)
                        .collect(Collectors.toSet())
        );
        //  转换并设置类型名称
        PageResult<DeviceModelAttributeRespVO> respPageResult = BeanUtils.toBean(pageResult, DeviceModelAttributeRespVO.class, deviceModelAttribute -> {
            String dataUnitStr = deviceModelAttribute.getDataUnit();
            if (StringUtils.isNotBlank(dataUnitStr)) {
                try {
                    Long dataUnitId = Long.valueOf(dataUnitStr.trim());
                    MapUtils.findAndThen(unitMap, dataUnitId,
                            unit -> deviceModelAttribute.setDataUnitName(unit.getName()));
                } catch (NumberFormatException e) {

                }
            }
        });

//        respPageResult.getList().forEach(item -> {
//            String typeName = typeNameMap.get(item.getAttributeType());
//            if (typeName != null) {
//                item.setTypeName(typeName);
//            }
//        });

        return respPageResult;
    }

    @Override
    public List<Map<String, Object>> operationAnalysisDetails(Long deviceId, Long modelId,
                                                              String collectionStartTime, String collectionEndTime) {
        if (deviceId == null) {
            throw exception(DEVICE_ID_DOES_NOT_EXIST);
        }
        if (modelId == null) {
            throw exception(POINT_ID_MODEL_NOT_EXISTS);
        }

        List<Map<String, Object>> resultList = new ArrayList<>();

        try {
            // 1. 获取最新10条设备数据列表（直接从TDengine获取原始字段）
            List<Map<String, Object>> deviceDataList =
                    tdengineService.newSelectLatestData(deviceId, collectionStartTime, collectionEndTime, 10);

            // 2. 获取属性类型映射
            Map<Long, String> idToNameMap = deviceAttributeTypeMapper.selectList()
                    .stream()
                    .collect(Collectors.toMap(
                            DeviceAttributeTypeDO::getId,
                            DeviceAttributeTypeDO::getName
                    ));

            // 3. 遍历每个时间点的数据
            for (Map<String, Object> deviceData : deviceDataList) {
                Timestamp timestamp = (Timestamp) deviceData.get("ts"); // TDengine 时间列
                if (timestamp == null) continue;

                SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
                String formattedTime = sdf.format(timestamp);

                Map<String, Object> timePointData = new LinkedHashMap<>();
                timePointData.put("collectTime", formattedTime);

                // 遍历所有字段（除 ts 之外）
                Map<String, List<Map<String, Object>>> groupedData = new LinkedHashMap<>();
                for (Map.Entry<String, Object> entry : deviceData.entrySet()) {
                    String key = entry.getKey();
                    if ("ts".equalsIgnoreCase(key)) continue; // 跳过时间字段

                    Map<String, Object> simplifiedData = new HashMap<>();
                    simplifiedData.put("attributeName", key);
                    simplifiedData.put("addressValue", entry.getValue());

                    // 根据 modelId 或 attributeType 分类，这里暂时按 "其他" 分组
                    groupedData.computeIfAbsent("其他", k -> new ArrayList<>()).add(simplifiedData);
                }

                // 添加属性分组
                for (Map.Entry<String, List<Map<String, Object>>> entry : groupedData.entrySet()) {
                    timePointData.put(entry.getKey(), entry.getValue());
                }

                resultList.add(timePointData);
            }

        } catch (Exception e) {
            log.error("处理设备 {} 数据时发生异常", deviceId, e);
            return new ArrayList<>();
        }

        return resultList;
    }

    @Override
    public List<DeviceModelAttributeDO> getDeviceModelAttributeList(Long id) {

        return deviceModelAttributeMapper.selectList(Wrappers.<DeviceModelAttributeDO>lambdaQuery().eq(DeviceModelAttributeDO::getDeviceModelId,id));
    }


    @Override
    @Transactional(rollbackFor = Exception.class) // 完全复用你的事务注解，异常回滚所有导入
    public DeviceModelAttributeImportRespVO importAttributeList(List<DeviceModelAttributeImportExcelVO> importAttributes, Long deviceModelId, boolean isUpdateSupport) {
        // 1.1 参数校验 - 完全复刻 User 的空列表校验逻辑
        if (CollUtil.isEmpty(importAttributes)) {
            throw exception(DEVICE_MODEL_ATTRIBUTE_NOT_EXISTS);
        }
        // 1.2 校验设备型号ID是否存在
        if (deviceModelId == null) {
            throw exception(DEVICE_MODEL_NOT_EXISTS);
        }

        // 2. 构建点位类型名称到ID的映射
        List<DeviceAttributeTypeDO> attributeTypes = deviceAttributeTypeMapper.selectList();
        Map<String, String> typeNameToIdMap = attributeTypes.stream()
                .collect(Collectors.toMap(DeviceAttributeTypeDO::getName, type -> String.valueOf(type.getId())));

        // 3. 初始化返回 VO - 完全复刻 User 的 builder 方式，使用 LinkedHashMap 保持顺序
        DeviceModelAttributeImportRespVO respVO = DeviceModelAttributeImportRespVO.builder()
                .createCodes(new ArrayList<>())
                .updateCodes(new ArrayList<>())
                .failureCodes(new LinkedHashMap<>())
                .build();

        // 4. 遍历，逐个创建 or 更新 - 完全复刻 User 的 forEach 逻辑
        importAttributes.forEach(importAttribute -> {
            // 4.1 设置设备型号ID
            importAttribute.setDeviceModelId(deviceModelId);

            // 4.2 处理点位类型转换
            String typeName = importAttribute.getTypeName();
            if (StringUtils.isBlank(typeName)) {
                respVO.getFailureCodes().put(importAttribute.getAttributeCode(), "点位类型名称不能为空");
                return;
            }
            String attributeTypeId = typeNameToIdMap.get(typeName);
            if (StringUtils.isBlank(attributeTypeId)) {
                respVO.getFailureCodes().put(importAttribute.getAttributeCode(), "点位类型名称无效: " + typeName);
                return;
            }
            // 设置点位类型ID
            importAttribute.setAttributeType(attributeTypeId);

            // 4.3.1 校验字段是否符合要求 - 完全复刻 User 的 ValidationUtils.validate 调用
            try {
                // 注意：如果有 DeviceModelAttributeSaveReqVO，替换为该 VO；无则直接校验 importAttribute
                ValidationUtils.validate(BeanUtils.toBean(importAttribute, DeviceModelAttributeSaveReqVO.class));
            } catch (ConstraintViolationException ex) {
                respVO.getFailureCodes().put(importAttribute.getAttributeCode(), ex.getMessage());
                return;
            }

            // 4.3.2 业务规则校验 - 完全复刻 User 的 validateUserForCreateOrUpdate 逻辑
            try {
                validateAttributeForCreateOrUpdate(deviceModelId, importAttribute.getAttributeCode());
            } catch (ServiceException ex) {
                respVO.getFailureCodes().put(importAttribute.getAttributeCode(), ex.getMessage());
                return;
            }

            // 4.4.1 判断如果不存在，进行插入 - 完全复刻 User 的 selectByUsername 逻辑
            DeviceModelAttributeDO existAttribute = deviceModelAttributeMapper.selectByAttributeCode(importAttribute.getAttributeCode());
            if (existAttribute == null) {
                // 创建DO对象并设置点位类型名称
                DeviceModelAttributeDO deviceModelAttribute = BeanUtils.toBean(importAttribute, DeviceModelAttributeDO.class);
                deviceModelAttribute.setTypeName(typeName); // 设置点位类型名称
                deviceModelAttributeMapper.insert(deviceModelAttribute);
                respVO.getCreateCodes().add(importAttribute.getAttributeCode());
                return;
            }

            // 4.4.2 如果存在，判断是否允许更新 - 完全复刻 User 的更新逻辑
            if (!isUpdateSupport) {
                respVO.getFailureCodes().put(importAttribute.getAttributeCode(), DEVICE_MODEL_ATTRIBUTE_NOT_EXISTS.getMsg());
                return;
            }

            // 创建更新对象并设置点位类型名称
            DeviceModelAttributeDO updateAttribute = BeanUtils.toBean(importAttribute, DeviceModelAttributeDO.class);
            updateAttribute.setId(existAttribute.getId()); // 复用已有数据的 ID
            updateAttribute.setTypeName(typeName); // 设置点位类型名称
            deviceModelAttributeMapper.updateById(updateAttribute);
            respVO.getUpdateCodes().add(importAttribute.getAttributeCode());
        });

        return respVO;
    }

    /**
     * 校验设备采集点位创建/更新的业务规则
     * 【对应 User 的 validateUserForCreateOrUpdate 方法】
     */
    private void validateAttributeForCreateOrUpdate(Long deviceModelId, String code) {
        // 1. 校验设备型号是否存在（可根据你的业务补充，对应 User 的部门校验）
        if (deviceModelId == null) {
            throw exception(ErrorCodeConstants.DEVICE_MODEL_NOT_EXISTS); // 替换为你项目中的设备型号不存在错误码
        }
        // 2. 可补充其他业务校验（如数据类型合法性、单位长度等）
    }







}