package com.aiotagro.cattletrade.business.service;

import com.aiotagro.cattletrade.business.entity.IotDeviceData;
import com.aiotagro.cattletrade.business.entity.JbqClientLog;
import com.aiotagro.cattletrade.business.entity.JbqServerLog;
import com.aiotagro.cattletrade.business.entity.XqClientLog;
import com.aiotagro.cattletrade.business.mapper.IotDeviceDataMapper;
import com.aiotagro.cattletrade.business.mapper.JbqClientLogMapper;
import com.aiotagro.cattletrade.business.mapper.JbqServerLogMapper;
import com.aiotagro.cattletrade.business.mapper.XqClientLogMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.util.Date;
import java.util.List;
import java.util.ArrayList;

/**
 * IoT设备日志同步服务
 * 每60分钟从iot_device_data表同步数据到对应的日志表
 *
 * @author System
 * @date 2025-01-16
 */
@Service
public class IotDeviceLogSyncService {

    private static final Logger logger = LoggerFactory.getLogger(IotDeviceLogSyncService.class);

    @Autowired
    private IotDeviceDataMapper iotDeviceDataMapper;

    @Autowired
    private JbqClientLogMapper jbqClientLogMapper;

    @Autowired
    private JbqServerLogMapper jbqServerLogMapper;

    @Autowired
    private XqClientLogMapper xqClientLogMapper;

    /**
     * 同步设备数据到日志表
     * 每60分钟执行一次
     */
    @Transactional
    public void syncDeviceDataToLogs() {
        try {
            logger.info("========== 开始执行设备日志同步任务 ==========");

            // 只查询绑定了运送清单的设备数据（delivery_id 不为空）
            QueryWrapper<IotDeviceData> queryWrapper = new QueryWrapper<>();
            queryWrapper.isNotNull("delivery_id");
            List<IotDeviceData> allDevices = iotDeviceDataMapper.selectList(queryWrapper);
            
            if (allDevices.isEmpty()) {
                logger.warn("未找到任何绑定了运送清单的设备数据");
                return;
            }

            logger.info("找到 {} 个绑定了运送清单的设备，开始同步到日志表", allDevices.size());
            
            // ✅ 统计有经纬度数据的设备数量
            long devicesWithCoordinates = allDevices.stream()
                .filter(device -> device.getLatitude() != null && device.getLongitude() != null)
                .filter(device -> {
                    String lat = sanitizeCoordinate(device.getLatitude());
                    String lng = sanitizeCoordinate(device.getLongitude());
                    return lat != null && lng != null && !lat.equals("0") && !lng.equals("0");
                })
                .count();
            logger.info("其中 {} 个设备包含有效的经纬度坐标数据", devicesWithCoordinates);
            logger.info("注意：设备日志同步任务仅将数据同步到日志表，不直接上传到百度鹰眼服务");
            logger.info("百度鹰眼轨迹上传由 DeliveryYingyanSyncService 定时任务负责");

            int hostCount = 0;
            int earTagCount = 0;
            int collarCount = 0;

            // 按设备类型分组，准备批量插入
            List<JbqServerLog> hostLogs = new ArrayList<>();
            List<JbqClientLog> earTagLogs = new ArrayList<>();
            List<XqClientLog> collarLogs = new ArrayList<>();

            // 遍历所有设备，根据设备类型分组
            int devicesWithCoordinatesCount = 0;
            for (IotDeviceData device : allDevices) {
                try {
                    Integer deviceType = device.getDeviceType();
                    
                    if (deviceType == null) {
                        logger.warn("设备 {} 的设备类型为空，跳过", device.getDeviceId());
                        continue;
                    }
                    
                    // ✅ 记录设备经纬度信息
                    boolean hasValidCoordinates = false;
                    if (device.getLatitude() != null && device.getLongitude() != null) {
                        String lat = sanitizeCoordinate(device.getLatitude());
                        String lng = sanitizeCoordinate(device.getLongitude());
                        if (lat != null && lng != null && !lat.equals("0") && !lng.equals("0")) {
                            hasValidCoordinates = true;
                            devicesWithCoordinatesCount++;
                            logger.debug("设备 {} (类型: {}, 运单ID: {}) 包含经纬度坐标 - 纬度: {}, 经度: {}", 
                                device.getDeviceId(), deviceType, device.getDeliveryId(), lat, lng);
                        }
                    }
                    if (!hasValidCoordinates) {
                        logger.debug("设备 {} (类型: {}, 运单ID: {}) 无有效经纬度坐标", 
                            device.getDeviceId(), deviceType, device.getDeliveryId());
                    }

                    switch (deviceType) {
                        case 1: // 主机设备
                            hostLogs.add(convertToHostLog(device));
                            hostCount++;
                            break;
                        case 2: // 耳标设备
                            earTagLogs.add(convertToEarTagLog(device));
                            earTagCount++;
                            break;
                        case 4: // 项圈设备
                            XqClientLog collarLog = convertToCollarLog(device);
                            if (collarLog != null) {
                                collarLogs.add(collarLog);
                                collarCount++;
                            } else {
                                logger.warn("设备 {} 的项圈日志转换失败，跳过", device.getDeviceId());
                            }
                            break;
                        default:
                            logger.warn("未知设备类型: {} for device: {}", deviceType, device.getDeviceId());
                            break;
                    }
                } catch (Exception e) {
                    logger.error("处理设备 {} 数据失败", device.getDeviceId(), e);
                }
            }

            // 逐条插入日志数据 - 方案一：使用逐条插入替代批量插入
            if (!hostLogs.isEmpty()) {
                logger.info("准备逐条插入主机日志 {} 条", hostLogs.size());
                int hostSuccessCount = 0;
                for (int i = 0; i < hostLogs.size(); i++) {
                    JbqServerLog log = hostLogs.get(i);
                    try {
                        logger.info("尝试插入第{}条主机日志 - deviceId: {}", i + 1, log.getDeviceId());
                        jbqServerLogMapper.insert(log);
                        hostSuccessCount++;
                        logger.info("第{}条主机日志插入成功", i + 1);
                    } catch (Exception ex) {
                        logger.error("插入第{}条主机日志失败 - deviceId: {}, error: {}", 
                            i + 1, log.getDeviceId(), ex.getMessage(), ex);
                    }
                }
                logger.info("逐条插入主机日志完成，成功 {} 条，失败 {} 条", hostSuccessCount, hostLogs.size() - hostSuccessCount);
            }
            
            if (!earTagLogs.isEmpty()) {
                logger.info("准备逐条插入耳标日志 {} 条", earTagLogs.size());
                int earTagSuccessCount = 0;
                for (int i = 0; i < earTagLogs.size(); i++) {
                    JbqClientLog log = earTagLogs.get(i);
                    try {
                        logger.info("尝试插入第{}条耳标日志 - deviceId: {}", i + 1, log.getDeviceId());
                        jbqClientLogMapper.insert(log);
                        earTagSuccessCount++;
                        logger.info("第{}条耳标日志插入成功", i + 1);
                    } catch (Exception ex) {
                        logger.error("插入第{}条耳标日志失败 - deviceId: {}, error: {}", 
                            i + 1, log.getDeviceId(), ex.getMessage(), ex);
                    }
                }
                logger.info("逐条插入耳标日志完成，成功 {} 条，失败 {} 条", earTagSuccessCount, earTagLogs.size() - earTagSuccessCount);
            }
            
            if (!collarLogs.isEmpty()) {
                logger.info("准备逐条插入项圈日志 {} 条", collarLogs.size());
                int collarSuccessCount = 0;
                for (int i = 0; i < collarLogs.size(); i++) {
                    XqClientLog log = collarLogs.get(i);
                    try {
                        logger.info("尝试插入第{}条项圈日志 - deviceId: {}, latitude: {}, longitude: {}, voltage: {}, temp: {}, serverDeviceId: {}",
                            i + 1, log.getDeviceId(), log.getLatitude(), log.getLongitude(), 
                            log.getDeviceVoltage(), log.getDeviceTemp(), log.getServerDeviceId());
                        xqClientLogMapper.insert(log);
                        collarSuccessCount++;
                        logger.info("第{}条项圈日志插入成功", i + 1);
                    } catch (Exception ex) {
                        logger.error("插入第{}条项圈日志失败 - deviceId: {}, latitude: {}, longitude: {}, voltage: {}, temp: {}, serverDeviceId: {}, error: {}",
                            i + 1, log.getDeviceId(), log.getLatitude(), log.getLongitude(), 
                            log.getDeviceVoltage(), log.getDeviceTemp(), log.getServerDeviceId(), ex.getMessage(), ex);
                    }
                }
                logger.info("逐条插入项圈日志完成，成功 {} 条，失败 {} 条", collarSuccessCount, collarLogs.size() - collarSuccessCount);
            }

            logger.info("设备日志同步完成 - 主机: {}, 耳标: {}, 项圈: {}", hostCount, earTagCount, collarCount);
            logger.info("包含有效经纬度坐标的设备数量: {}", devicesWithCoordinatesCount);
            logger.info("========== 设备日志同步任务执行完成 ==========");
            logger.info("提示：同步到日志表的经纬度数据将由 DeliveryYingyanSyncService 定时任务上传到百度鹰眼服务");

        } catch (Exception e) {
            logger.error("设备日志同步任务执行失败", e);
            throw e;
        }
    }

    /**
     * 将主机设备数据转换为日志对象
     */
    private JbqServerLog convertToHostLog(IotDeviceData device) {
        JbqServerLog log = new JbqServerLog();
        
        // 设置设备基本信息
        log.setDeviceId(device.getDeviceId());
        
        // 设置设备数据
        if (device.getVoltage() != null) {
            log.setDeviceVoltage(device.getVoltage().toString());
        }
        if (device.getTemperature() != null) {
            log.setDeviceTemp(device.getTemperature().toString());
        }
        if (device.getSteps() != null) {
            log.setWalkSteps(device.getSteps());
        }
        if (device.getSameDaySteps() != null) {
            log.setYWalkSteps(device.getSameDaySteps().longValue());
        }
        if (device.getLatitude() != null) {
            String lat = sanitizeCoordinate(device.getLatitude());
            if (lat != null) {
                log.setLatitude(lat);
            }
        }
        if (device.getLongitude() != null) {
            String lng = sanitizeCoordinate(device.getLongitude());
            if (lng != null) {
                log.setLongitude(lng);
            }
        }
        
        // 设置时间字段
        Date now = new Date();
        log.setCreateTime(now);
        log.setUpdateTime(now);
        log.setCreateBy("SYSTEM");
        log.setUpdateBy("SYSTEM");
        
        return log;
    }

    /**
     * 将耳标设备数据转换为日志对象
     */
    private JbqClientLog convertToEarTagLog(IotDeviceData device) {
        JbqClientLog log = new JbqClientLog();
        
        // 设置设备基本信息
        log.setDeviceId(device.getDeviceId());
        
        // 设置设备数据
        if (device.getVoltage() != null) {
            log.setDeviceVoltage(device.getVoltage().toString());
        }
        if (device.getTemperature() != null) {
            log.setDeviceTemp(device.getTemperature().toString());
        }
        if (device.getSteps() != null) {
            log.setWalkSteps(device.getSteps());
        }
        if (device.getSameDaySteps() != null) {
            log.setYWalkSteps(device.getSameDaySteps().longValue());
        }
        if (device.getLatitude() != null) {
            String lat = sanitizeCoordinate(device.getLatitude());
            if (lat != null) {
                log.setLatitude(lat);
            }
        }
        if (device.getLongitude() != null) {
            String lng = sanitizeCoordinate(device.getLongitude());
            if (lng != null) {
                log.setLongitude(lng);
            }
        }
        
        // 设置时间字段
        Date now = new Date();
        log.setCreateTime(now);
        log.setUpdateTime(now);
        log.setCreateBy("SYSTEM");
        log.setUpdateBy("SYSTEM");
        
        return log;
    }

    /**
     * 将项圈设备数据转换为日志对象
     * 注意：xq_client_log表的实际字段是battery, temperature等，不是device_voltage, device_temp
     */
    private XqClientLog convertToCollarLog(IotDeviceData device) {
        XqClientLog log = new XqClientLog();
        
        // 设置设备基本信息
        log.setDeviceId(device.getDeviceId());
        
        // 设置serverDeviceId - iot_device_data表中没有此字段，设置为null
        log.setServerDeviceId(null);
        
        // 设置设备数据 - 使用更安全的数据转换
        if (device.getVoltage() != null) {
            // 使用String.format确保精度控制
            String voltageStr = String.format("%.3f", device.getVoltage().doubleValue());
            log.setDeviceVoltage(voltageStr);
        }
        if (device.getTemperature() != null) {
            // 使用String.format确保精度控制
            String tempStr = String.format("%.2f", device.getTemperature().doubleValue());
            log.setDeviceTemp(tempStr);
        }
        if (device.getSteps() != null) {
            log.setWalkSteps(device.getSteps());
        }
        if (device.getSameDaySteps() != null) {
            log.setYWalkSteps(device.getSameDaySteps().longValue());
        }
        // 处理latitude和longitude - 修改逻辑：只有当两个坐标都无效时才跳过
        boolean hasValidLatitude = false;
        boolean hasValidLongitude = false;
        
        if (device.getLatitude() != null) {
            // latitude是String类型，直接使用
            String latStr = device.getLatitude();
            latStr = sanitizeCoordinate(latStr);
            
            // 检查是否为无效坐标
            if (latStr != null && !latStr.equals("0") && !latStr.trim().isEmpty() && !latStr.equals("null") && !latStr.equals("NULL")) {
                hasValidLatitude = true;
                log.setLatitude(latStr);
            } else {
                logger.warn("设备 {} 的latitude数据无效: {}", device.getDeviceId(), latStr);
            }
        }
        
        if (device.getLongitude() != null) {
            // longitude是String类型，直接使用
            String lngStr = device.getLongitude();
            lngStr = sanitizeCoordinate(lngStr);
            
            // 检查是否为无效坐标
            if (lngStr != null && !lngStr.equals("0") && !lngStr.trim().isEmpty() && !lngStr.equals("null") && !lngStr.equals("NULL")) {
                hasValidLongitude = true;
                log.setLongitude(lngStr);
            } else {
                logger.warn("设备 {} 的longitude数据无效: {}", device.getDeviceId(), lngStr);
            }
        }
        
        // 只有当两个坐标都无效时才跳过这条数据
        if (!hasValidLatitude && !hasValidLongitude) {
            logger.warn("设备 {} 的latitude和longitude都无效，跳过", device.getDeviceId());
            return null;
        }
        
        // 设置时间字段
        Date now = new Date();
        log.setCreateTime(now);
        log.setUpdateTime(now);
        log.setCreateBy("SYSTEM");
        log.setUpdateBy("SYSTEM");
        
        return log;
    }

    /**
     * 规范化经纬度字符串，移除首尾空格，限制最大长度，过滤无效字面量
     */
    private String sanitizeCoordinate(String coord) {
        if (coord == null) {
            return null;
        }
        String v = coord.trim();
        if (v.isEmpty()) {
            return null;
        }
        if ("null".equalsIgnoreCase(v)) {
            return null;
        }
        // 限长，避免超过数据库字段长度
        if (v.length() > 32) {
            v = v.substring(0, 32);
        }
        return v;
    }
    /**
     * 获取设备日志同步统计信息
     */
    public void logSyncStatistics() {
        try {
            // 统计各日志表的记录数
            long hostLogCount = jbqServerLogMapper.selectCount(null);
            long earTagLogCount = jbqClientLogMapper.selectCount(null);
            long collarLogCount = xqClientLogMapper.selectCount(null);
            
            logger.info("日志表统计 - 主机日志: {}, 耳标日志: {}, 项圈日志: {}", 
                hostLogCount, earTagLogCount, collarLogCount);
                
        } catch (Exception e) {
            logger.error("获取日志同步统计信息失败", e);
        }
    }
}
