package com.aiotagro.cattletrade.business.service;

import com.aiotagro.cattletrade.business.entity.IotDeviceData;
import com.aiotagro.cattletrade.business.entity.IotSyncLog;
import com.aiotagro.cattletrade.business.mapper.IotDeviceDataMapper;
import com.aiotagro.cattletrade.business.mapper.IotSyncLogMapper;
import com.aiotagro.cattletrade.common.utils.http.HttpUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.Set;
import java.util.HashSet;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

/**
 * IoT设备数据同步服务
 *
 * @author System
 * @date 2025-01-16
 */
@Service
public class IotDeviceSyncService {

    private static final Logger logger = LoggerFactory.getLogger(IotDeviceSyncService.class);
    
    private static final String IOT_API_URL = "http://api.aiotagro.com/api/iot/organ/deviceStatus";
    private static final String ORGAN_ID = "385082";
    private static final String SECRET_KEY = "8A71C63863394F8D5C36A8809F2C0875";
    
    @Autowired
    private IotDeviceDataMapper iotDeviceDataMapper;
    
    @Autowired
    private IotSyncLogMapper iotSyncLogMapper;

    /**
     * 同步IoT设备数据
     */
    @Transactional
    public void syncIotDeviceData() {
        IotSyncLog syncLog = new IotSyncLog();
        syncLog.setSyncType("AUTO");
        syncLog.setSyncTime(LocalDateTime.now());
        
        try {
            logger.info("开始同步IoT设备数据");
            
            // 调用外部API获取数据
            List<Map<String, Object>> deviceDataList = fetchDeviceDataFromApi();
            
            // 提取API返回的设备ID集合
            Set<String> apiDeviceIds = new HashSet<>();
            for (Map<String, Object> deviceData : deviceDataList) {
                if (deviceData.get("deviceId") != null) {
                    apiDeviceIds.add(String.valueOf(deviceData.get("deviceId")));
                }
            }
            
            if (apiDeviceIds.isEmpty()) {
                logger.warn("未获取到设备数据");
                syncLog.setSyncStatus("SUCCESS");
                syncLog.setTotalCount(0);
                syncLog.setSuccessCount(0);
                syncLog.setFailedCount(0);
                iotSyncLogMapper.insert(syncLog);
                return;
            }
            
            syncLog.setTotalCount(deviceDataList.size());
            int successCount = 0;
            int failedCount = 0;
            int restoredCount = 0; // 统计恢复的设备数量
            
            // 批量保存数据
            for (Map<String, Object> deviceData : deviceDataList) {
                try {
                    IotDeviceData iotDevice = convertToIotDeviceData(deviceData);
                    
                    // 检查设备是否已存在
                    IotDeviceData existingDevice = iotDeviceDataMapper.selectOne(
                        new QueryWrapper<IotDeviceData>()
                            .eq("device_id", iotDevice.getDeviceId())
                    );
                    
                    if (existingDevice != null) {
                        // 更新现有设备数据
                        iotDevice.setId(existingDevice.getId());
                        iotDevice.setCreateTime(existingDevice.getCreateTime());
                        // 保留已有的deliveryId和tenantId
                        iotDevice.setDeliveryId(existingDevice.getDeliveryId());
                        iotDevice.setTenantId(existingDevice.getTenantId());
                        
                        // 检查设备是否从逻辑删除状态恢复
                        if (existingDevice.getIsDelet() != null && existingDevice.getIsDelet() == 1) {
                            logger.info("设备重新绑定，恢复为正常状态: deviceId={}, deliveryId={}, tenantId={}", 
                                iotDevice.getDeviceId(), existingDevice.getDeliveryId(), existingDevice.getTenantId());
                            restoredCount++;
                        }
                        
                        // 设备在API中返回，标记为正常状态
                        iotDevice.setIsDelet(0);
                        iotDeviceDataMapper.updateById(iotDevice);
                        logger.debug("更新设备数据: {}, 更新时间: {}", iotDevice.getDeviceId(), iotDevice.getUpdateTime());
                    } else {
                        // 插入新设备数据，默认为正常状态
                        iotDevice.setIsDelet(0);
                        iotDeviceDataMapper.insert(iotDevice);
                        logger.debug("插入新设备数据: {}, 创建时间: {}", iotDevice.getDeviceId(), iotDevice.getCreateTime());
                    }
                    
                    successCount++;
                } catch (Exception e) {
                    logger.error("处理设备数据失败: {}", deviceData.get("deviceId"), e);
                    failedCount++;
                }
            }
            
            // 输出恢复统计
            if (restoredCount > 0) {
                logger.info("本次同步恢复了 {} 个重新绑定的设备", restoredCount);
            }
            
            // 清理已被重新分配到其他项目的设备
            try {
                cleanupReassignedDevices(apiDeviceIds);
            } catch (Exception e) {
                logger.error("清理重新分配设备失败", e);
            }
            
            syncLog.setSyncStatus(failedCount > 0 ? "FAILED" : "SUCCESS");
            syncLog.setSuccessCount(successCount);
            syncLog.setFailedCount(failedCount);
            
            logger.info("IoT设备数据同步完成，总数: {}, 成功: {}, 失败: {}, 恢复: {}", 
                deviceDataList.size(), successCount, failedCount, restoredCount);
            
        } catch (Exception e) {
            logger.error("同步IoT设备数据失败", e);
            syncLog.setSyncStatus("FAILED");
            syncLog.setErrorMessage(e.getMessage());
        } finally {
            iotSyncLogMapper.insert(syncLog);
        }
    }

    /**
     * 从外部API获取设备数据
     */
    private List<Map<String, Object>> fetchDeviceDataFromApi() throws Exception {
        // 生成签名
        long currentTimestamp = System.currentTimeMillis();
        String sign = generateSign(ORGAN_ID, String.valueOf(currentTimestamp), SECRET_KEY);
        
        Map<String, Object> params = new HashMap<>();
        params.put("organId", ORGAN_ID);
        params.put("timestamp", currentTimestamp);
        params.put("sign", sign);
        
        logger.info("调用外部API获取设备数据");
        String response = HttpUtils.sendPost(IOT_API_URL, params);
        
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> responseMap = mapper.readValue(response, Map.class);
        
        if (!Integer.valueOf(0).equals(responseMap.get("status"))) {
            throw new RuntimeException("外部API调用失败: " + responseMap.get("msg"));
        }
        
        List<Map<String, Object>> allDevices = new ArrayList<>();
        
        if (responseMap.containsKey("data") && responseMap.get("data") instanceof Map) {
            Map<String, Object> dataMap = (Map<String, Object>) responseMap.get("data");
            
            if (dataMap.containsKey("devices") && dataMap.get("devices") instanceof List) {
                List<Map<String, Object>> devicesList = (List<Map<String, Object>>) dataMap.get("devices");
                
                for (Map<String, Object> deviceGroup : devicesList) {
                    if (deviceGroup.containsKey("detail") && deviceGroup.get("detail") instanceof List) {
                        List<Map<String, Object>> details = (List<Map<String, Object>>) deviceGroup.get("detail");
                        Integer type = (Integer) deviceGroup.get("type");
                        
                        for (Map<String, Object> detail : details) {
                            detail.put("type", type);
                            // 根据type设置name字段
                            if (type == 1) {
                                detail.put("name", "主机");
                            } else if (type == 2) {
                                detail.put("name", "耳标");
                            } else if (type == 4) {
                                detail.put("name", "项圈");
                            }
                            
                            // 记录设备数据字段，用于调试
                            logger.debug("设备数据字段: deviceId={}, voltage={}, temperature={}, steps={}, signal={}, latitude={}, longitude={}", 
                                detail.get("deviceId"), detail.get("voltage"), detail.get("temperature"), 
                                detail.get("steps"), detail.get("signal"), detail.get("latitude"), detail.get("longitude"));
                            
                            allDevices.add(detail);
                        }
                    }
                }
            }
        }
        
        return allDevices;
    }

    /**
     * 将API数据转换为实体对象
     */
    private IotDeviceData convertToIotDeviceData(Map<String, Object> data) {
        IotDeviceData device = new IotDeviceData();
        
        device.setDeviceId(String.valueOf(data.get("deviceId")));
        device.setDeviceType((Integer) data.get("type"));
        
        logger.debug("开始转换设备数据: deviceId={}, type={}", device.getDeviceId(), device.getDeviceType());
        
        // 设置设备名称，确保字符编码正确
        String deviceName = String.valueOf(data.get("name"));
        if (deviceName != null && !deviceName.equals("null")) {
            device.setDeviceName(deviceName);
        } else {
            // 如果name字段为空，根据type设置默认名称
            Integer type = device.getDeviceType();
            if (type == 1) {
                device.setDeviceName("主机");
            } else if (type == 2) {
                device.setDeviceName("耳标");
            } else if (type == 4) {
                device.setDeviceName("项圈");
            } else {
                device.setDeviceName("未知设备");
            }
        }
        device.setOrganId(ORGAN_ID);
        
        // 电压和电量
        if (data.get("voltage") != null) {
            device.setVoltage(new BigDecimal(String.valueOf(data.get("voltage"))));
            device.setBatteryPercentage(calculateBatteryPercentage(device.getVoltage()));
            logger.debug("设置电压: {}, 电量百分比: {}", device.getVoltage(), device.getBatteryPercentage());
        }
        if (data.get("battery") != null) {
            device.setVoltage(new BigDecimal(String.valueOf(data.get("battery"))));
            device.setBatteryPercentage(calculateBatteryPercentage(device.getVoltage()));
            logger.debug("设置电池电压: {}, 电量百分比: {}", device.getVoltage(), device.getBatteryPercentage());
        }
        
        // 温度
        if (data.get("temperature") != null && !String.valueOf(data.get("temperature")).isEmpty()) {
            device.setTemperature(new BigDecimal(String.valueOf(data.get("temperature"))));
            logger.debug("设置温度: {}", device.getTemperature());
        }
        
        // 步数
        if (data.get("steps") != null) {
            device.setSteps(Long.valueOf(String.valueOf(data.get("steps"))));
            logger.debug("设置步数: {}", device.getSteps());
        }
        
        // 当日步数
        if (data.get("sameDaySteps") != null) {
            device.setSameDaySteps(Integer.valueOf(String.valueOf(data.get("sameDaySteps"))));
            logger.debug("设置当日步数: {}", device.getSameDaySteps());
        }
        
        // 信号强度
        if (data.get("signal") != null) {
            device.setSignalStrength(String.valueOf(data.get("signal")));
            logger.debug("设置信号强度: {}", device.getSignalStrength());
        }
        if (data.get("rsrp") != null) {
            device.setRsrp(String.valueOf(data.get("rsrp")));
            logger.debug("设置RSRP信号强度: {}", device.getRsrp());
        }
        
        // GPS状态
        if (data.get("gpsState") != null) {
            device.setGpsState(String.valueOf(data.get("gpsState")));
            logger.debug("设置GPS状态: {}", device.getGpsState());
        }
        
        // 位置信息
        if (data.get("latitude") != null) {
            device.setLatitude(String.valueOf(data.get("latitude")));
            logger.debug("设置纬度: {}", device.getLatitude());
        }
        if (data.get("longitude") != null) {
            device.setLongitude(String.valueOf(data.get("longitude")));
            logger.debug("设置经度: {}", device.getLongitude());
        }
        if (data.get("altitude") != null) {
            device.setAltitude(String.valueOf(data.get("altitude")));
            logger.debug("设置海拔: {}", device.getAltitude());
        }
        
        // 设备状态
        if (data.get("status") != null) {
            device.setStatus(Integer.valueOf(String.valueOf(data.get("status"))));
            logger.debug("设置设备状态: {}", device.getStatus());
        }
        
        // 版本
        if (data.get("ver") != null) {
            device.setVersion(String.valueOf(data.get("ver")));
            logger.debug("设置设备版本: {}", device.getVersion());
        }
        
        // 更新时间
        if (data.get("uptime") != null) {
            try {
                String uptimeStr = String.valueOf(data.get("uptime"));
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                device.setUptime(LocalDateTime.parse(uptimeStr, formatter));
                logger.debug("设置设备运行时间: {}", device.getUptime());
            } catch (Exception e) {
                logger.warn("解析更新时间失败: {}", data.get("uptime"));
            }
        }
        
        // 设置数据同步时间
        device.setUpdateTime(LocalDateTime.now());
        logger.debug("设置数据同步时间: {}", device.getUpdateTime());
        
        logger.debug("设备数据转换完成: deviceId={}, voltage={}, temperature={}, steps={}, latitude={}, longitude={}", 
            device.getDeviceId(), device.getVoltage(), device.getTemperature(), 
            device.getSteps(), device.getLatitude(), device.getLongitude());
        
        return device;
    }

    /**
     * 计算电量百分比
     */
    private Integer calculateBatteryPercentage(BigDecimal voltage) {
        if (voltage == null) {
            return 0;
        }
        
        BigDecimal minVoltage = new BigDecimal("2.4");
        BigDecimal maxVoltage = new BigDecimal("3.0");
        
        if (voltage.compareTo(maxVoltage) >= 0) {
            return 100;
        } else if (voltage.compareTo(minVoltage) <= 0) {
            return 0;
        } else {
            BigDecimal percentage = voltage.subtract(minVoltage)
                .divide(maxVoltage.subtract(minVoltage), 4, BigDecimal.ROUND_HALF_UP)
                .multiply(new BigDecimal("100"));
            return percentage.intValue();
        }
    }

    /**
     * 生成签名
     */
    private String generateSign(String organId, String timestamp, String secretKey) {
        try {
            String data = organId + timestamp + secretKey;
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(data.getBytes("UTF-8"));
            
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (Exception e) {
            logger.error("生成签名失败", e);
            return "";
        }
    }

    /**
     * 标记已换绑的设备为逻辑删除状态
     * 不在API返回列表中的设备，将is_delet标记为1
     */
    private void cleanupReassignedDevices(Set<String> apiDeviceIds) {
        try {
            logger.info("开始标记已换绑的设备");
            
            // 查询数据库中所有正常状态的设备（is_delet=0或null）
            QueryWrapper<IotDeviceData> queryWrapper = new QueryWrapper<>();
            queryWrapper.and(wrapper -> wrapper.eq("is_delet", 0).or().isNull("is_delet"));
            List<IotDeviceData> allDevices = iotDeviceDataMapper.selectList(queryWrapper);
            
            int markedCount = 0;
            for (IotDeviceData device : allDevices) {
                // 如果设备不在API返回列表中，说明已经换绑到其他项目
                if (!apiDeviceIds.contains(device.getDeviceId())) {
                    // 标记为逻辑删除
                    device.setIsDelet(1);
                    device.setUpdateTime(LocalDateTime.now());
                    iotDeviceDataMapper.updateById(device);
                    logger.info("标记已换绑的设备为逻辑删除: deviceId={}, tenantId={}, deliveryId={}", 
                        device.getDeviceId(), device.getTenantId(), device.getDeliveryId());
                    markedCount++;
                }
            }
            
            logger.info("标记完成，共标记 {} 个已换绑的设备", markedCount);
        } catch (Exception e) {
            logger.error("标记已换绑设备时发生错误", e);
            throw e;
        }
    }
}
