package com.ruoyi.blockchain.service.impl;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ruoyi.blockchain.domain.OracleData;
import com.ruoyi.blockchain.mapper.OracleDataMapper;
import com.ruoyi.blockchain.service.OracleService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;

/**
 * Oracle数据源服务实现类
 * 
 * @author ruoyi
 */
@Service
public class OracleServiceImpl implements OracleService {
    
    private static final Logger log = LoggerFactory.getLogger(OracleServiceImpl.class);
    
    @Autowired
    private OracleDataMapper oracleDataMapper;
    
    // Oracle数据缓存
    private final Map<String, Map<String, Object>> oracleCache = new ConcurrentHashMap<>();
    
    // Oracle状态缓存
    private final Map<String, Map<String, Object>> oracleStatusCache = new ConcurrentHashMap<>();
    
    // 数据更新调度器
    private final ScheduledExecutorService updateScheduler = Executors.newScheduledThreadPool(2);
    
    // 安全随机数生成器
    private final SecureRandom secureRandom = new SecureRandom();
    
    @Override
    public boolean registerOracle(Map<String, Object> oracleConfig) {
        try {
            String oracleName = (String) oracleConfig.get("oracleName");
            String oracleAddress = (String) oracleConfig.get("oracleAddress");
            String dataType = (String) oracleConfig.get("dataType");
            Long updateInterval = (Long) oracleConfig.get("updateInterval");
            
            log.info("注册Oracle数据源: name={}, address={}, type={}", oracleName, oracleAddress, dataType);
            
            // 1. 验证Oracle配置
            validateOracleConfig(oracleConfig);
            
            // 2. 检查Oracle是否已存在
            List<OracleData> existingOracles = oracleDataMapper.selectOracleDataByOracleName(oracleName);
            if (!existingOracles.isEmpty()) {
                throw new ServiceException("Oracle已存在: " + oracleName);
            }
            
            // 3. 创建Oracle数据记录
            OracleData oracleData = new OracleData();
            oracleData.setOracleName(oracleName);
            oracleData.setOracleAddress(oracleAddress);
            oracleData.setDataKey("default");
            oracleData.setDataValue("");
            oracleData.setDataType(dataType);
            oracleData.setUpdateInterval(updateInterval);
            oracleData.setOracleStatus("ACTIVE");
            oracleData.setValidationStatus("PENDING");
            oracleData.setDescription("Oracle数据源: " + oracleName);
            oracleData.setCreateTime(DateUtils.getNowDate());
            
            int result = oracleDataMapper.insertOracleData(oracleData);
            
            // 4. 初始化Oracle缓存
            if (result > 0) {
                initializeOracleCache(oracleName, oracleConfig);
                
                // 5. 启动数据更新任务
                startDataUpdateTask(oracleName, updateInterval);
            }
            
            boolean success = result > 0;
            log.info("Oracle注册{}: {}", success ? "成功" : "失败", oracleName);
            return success;
            
        } catch (Exception e) {
            log.error("Oracle注册失败", e);
            throw new ServiceException("Oracle注册失败: " + e.getMessage());
        }
    }
    
    @Override
    public Object getOracleData(String oracleName, String dataKey) {
        try {
            log.debug("获取Oracle数据: {} -> {}", oracleName, dataKey);
            
            // 1. 从缓存获取
            Map<String, Object> oracleDataCache = oracleCache.get(oracleName);
            if (oracleDataCache != null && oracleDataCache.containsKey(dataKey)) {
                Object cachedData = oracleDataCache.get(dataKey);
                log.debug("从缓存获取Oracle数据: {} -> {} = {}", oracleName, dataKey, cachedData);
                return cachedData;
            }
            
            // 2. 从数据库获取
            OracleData oracleData = oracleDataMapper.selectOracleDataByNameAndKey(oracleName, dataKey);
            if (oracleData != null) {
                Object data = parseDataValue(oracleData.getDataValue(), oracleData.getDataType());
                
                // 3. 更新缓存
                oracleCache.computeIfAbsent(oracleName, k -> new ConcurrentHashMap<>()).put(dataKey, data);
                
                log.debug("从数据库获取Oracle数据: {} -> {} = {}", oracleName, dataKey, data);
                return data;
            }
            
            // 4. 模拟外部数据源获取
            Object simulatedData = simulateExternalDataFetch(oracleName, dataKey);
            if (simulatedData != null) {
                // 保存到数据库
                saveOracleData(oracleName, dataKey, simulatedData);
                
                // 更新缓存
                oracleCache.computeIfAbsent(oracleName, k -> new ConcurrentHashMap<>()).put(dataKey, simulatedData);
                
                log.debug("从外部数据源获取Oracle数据: {} -> {} = {}", oracleName, dataKey, simulatedData);
                return simulatedData;
            }
            
            log.warn("未找到Oracle数据: {} -> {}", oracleName, dataKey);
            return null;
            
        } catch (Exception e) {
            log.error("获取Oracle数据失败: {} -> {}", oracleName, dataKey, e);
            throw new ServiceException("获取Oracle数据失败: " + e.getMessage());
        }
    }
    @Override
    public boolean validateOracleData(String oracleName, String dataKey, Object expectedValue) {
        try {
            log.debug("验证Oracle数据: {} -> {} = {}", oracleName, dataKey, expectedValue);
            
            // 1. 获取当前数据
            Object currentData = getOracleData(oracleName, dataKey);
            if (currentData == null) {
                log.warn("Oracle数据不存在: {} -> {}", oracleName, dataKey);
                return false;
            }
            
            // 2. 数据比较
            boolean isValid = compareData(currentData, expectedValue);
            
            // 3. 更新验证状态
            OracleData oracleData = oracleDataMapper.selectOracleDataByNameAndKey(oracleName, dataKey);
            if (oracleData != null) {
                String validationStatus = isValid ? "VALID" : "INVALID";
                oracleDataMapper.updateValidationStatus(oracleData.getOracleDataId(), validationStatus);
            }
            
            log.debug("Oracle数据验证{}: {} -> {}", isValid ? "通过" : "失败", oracleName, dataKey);
            return isValid;
            
        } catch (Exception e) {
            log.error("Oracle数据验证失败: {} -> {}", oracleName, dataKey, e);
            return false;
        }
    }
    
    @Override
    public boolean updateOracleData(String oracleName, Map<String, Object> dataUpdates) {
        try {
            log.info("更新Oracle数据: {} -> {}", oracleName, dataUpdates.size());
            
            boolean allSuccess = true;
            
            for (Map.Entry<String, Object> entry : dataUpdates.entrySet()) {
                String dataKey = entry.getKey();
                Object dataValue = entry.getValue();
                
                if ("signature".equals(dataKey)) {
                    continue; // 跳过签名字段
                }
                
                try {
                    // 1. 验证数据签名
                    String signature = (String) dataUpdates.get("signature");
                    if (!verifyDataSignature(oracleName, dataKey, dataValue, signature)) {
                        log.warn("Oracle数据签名验证失败: {} -> {}", oracleName, dataKey);
                        allSuccess = false;
                        continue;
                    }
                    
                    // 2. 更新数据库
                    OracleData oracleData = oracleDataMapper.selectOracleDataByNameAndKey(oracleName, dataKey);
                    if (oracleData != null) {
                        String serializedValue = serializeDataValue(dataValue, oracleData.getDataType());
                        String newSignature = generateDataSignature(oracleName, dataKey, dataValue);
                        
                        oracleDataMapper.updateOracleDataValue(
                            oracleData.getOracleDataId(),
                            serializedValue,
                            newSignature,
                            DateUtils.getNowDate()
                        );
                    } else {
                        // 创建新的数据记录
                        saveOracleData(oracleName, dataKey, dataValue);
                    }
                    
                    // 3. 更新缓存
                    oracleCache.computeIfAbsent(oracleName, k -> new ConcurrentHashMap<>()).put(dataKey, dataValue);
                    
                    log.debug("Oracle数据更新成功: {} -> {} = {}", oracleName, dataKey, dataValue);
                    
                } catch (Exception e) {
                    log.error("更新Oracle数据项失败: {} -> {}", oracleName, dataKey, e);
                    allSuccess = false;
                }
            }
            
            log.info("Oracle数据更新完成: {} -> success={}", oracleName, allSuccess);
            return allSuccess;
            
        } catch (Exception e) {
            log.error("Oracle数据更新失败: {}", oracleName, e);
            return false;
        }
    }
    
    @Override
    public Map<String, Object> getOracleStatus(String oracleName) {
        try {
            log.debug("获取Oracle状态: {}", oracleName);
            
            // 1. 从缓存获取
            Map<String, Object> cachedStatus = oracleStatusCache.get(oracleName);
            if (cachedStatus != null) {
                return new HashMap<>(cachedStatus);
            }
            
            // 2. 从数据库查询
            List<OracleData> oracleDataList = oracleDataMapper.selectOracleDataByOracleName(oracleName);
            if (oracleDataList.isEmpty()) {
                throw new ServiceException("Oracle不存在: " + oracleName);
            }
            
            // 3. 构建状态信息
            Map<String, Object> status = new HashMap<>();
            OracleData mainOracle = oracleDataList.get(0);
            
            status.put("oracleName", oracleName);
            status.put("oracleAddress", mainOracle.getOracleAddress());
            status.put("oracleStatus", mainOracle.getOracleStatus());
            status.put("dataCount", oracleDataList.size());
            status.put("lastUpdateTime", mainOracle.getLastUpdateTime());
            status.put("updateInterval", mainOracle.getUpdateInterval());
            
            // 统计验证状态
            long validCount = oracleDataList.stream().filter(d -> "VALID".equals(d.getValidationStatus())).count();
            long invalidCount = oracleDataList.stream().filter(d -> "INVALID".equals(d.getValidationStatus())).count();
            long pendingCount = oracleDataList.stream().filter(d -> "PENDING".equals(d.getValidationStatus())).count();
            
            status.put("validCount", validCount);
            status.put("invalidCount", invalidCount);
            status.put("pendingCount", pendingCount);
            status.put("validationRate", oracleDataList.size() > 0 ? (double) validCount / oracleDataList.size() : 0.0);
            
            // 4. 缓存状态信息
            oracleStatusCache.put(oracleName, new HashMap<>(status));
            
            log.debug("Oracle状态获取完成: {}", oracleName);
            return status;
            
        } catch (Exception e) {
            log.error("获取Oracle状态失败: {}", oracleName, e);
            throw new ServiceException("获取Oracle状态失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<Map<String, Object>> getAllOracles() {
        try {
            log.debug("获取所有Oracle列表");
            
            List<OracleData> allOracleData = oracleDataMapper.selectActiveOracleData();
            Map<String, Map<String, Object>> oracleMap = new HashMap<>();
            
            // 按Oracle名称分组
            for (OracleData oracleData : allOracleData) {
                String oracleName = oracleData.getOracleName();
                
                if (!oracleMap.containsKey(oracleName)) {
                    Map<String, Object> oracleInfo = new HashMap<>();
                    oracleInfo.put("oracleName", oracleName);
                    oracleInfo.put("oracleAddress", oracleData.getOracleAddress());
                    oracleInfo.put("oracleStatus", oracleData.getOracleStatus());
                    oracleInfo.put("dataType", oracleData.getDataType());
                    oracleInfo.put("updateInterval", oracleData.getUpdateInterval());
                    oracleInfo.put("createTime", oracleData.getCreateTime());
                    oracleInfo.put("dataCount", 0);
                    
                    oracleMap.put(oracleName, oracleInfo);
                }
                
                // 增加数据计数
                Map<String, Object> oracleInfo = oracleMap.get(oracleName);
                oracleInfo.put("dataCount", (Integer) oracleInfo.get("dataCount") + 1);
            }
            
            List<Map<String, Object>> result = new ArrayList<>(oracleMap.values());
            
            log.debug("Oracle列表获取完成: 共{}个Oracle", result.size());
            return result;
            
        } catch (Exception e) {
            log.error("获取Oracle列表失败", e);
            throw new ServiceException("获取Oracle列表失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean removeOracle(String oracleName) {
        try {
            log.warn("移除Oracle数据源: {}", oracleName);
            
            // 1. 删除数据库记录
            int result = oracleDataMapper.deleteOracleDataByOracleName(oracleName);
            
            // 2. 清理缓存
            oracleCache.remove(oracleName);
            oracleStatusCache.remove(oracleName);
            
            boolean success = result > 0;
            log.warn("Oracle移除{}: {}", success ? "成功" : "失败", oracleName);
            return success;
            
        } catch (Exception e) {
            log.error("移除Oracle失败: {}", oracleName, e);
            return false;
        }
    }
    
    // ==================== 私有辅助方法 ====================
    
    /**
     * 验证Oracle配置
     */
    private void validateOracleConfig(Map<String, Object> oracleConfig) {
        if (oracleConfig.get("oracleName") == null || oracleConfig.get("oracleName").toString().trim().isEmpty()) {
            throw new ServiceException("Oracle名称不能为空");
        }
        
        if (oracleConfig.get("oracleAddress") == null || oracleConfig.get("oracleAddress").toString().trim().isEmpty()) {
            throw new ServiceException("Oracle地址不能为空");
        }
        
        if (oracleConfig.get("dataType") == null || oracleConfig.get("dataType").toString().trim().isEmpty()) {
            throw new ServiceException("数据类型不能为空");
        }
        
        if (oracleConfig.get("updateInterval") == null || (Long) oracleConfig.get("updateInterval") <= 0) {
            throw new ServiceException("更新间隔必须大于0");
        }
    }
    
    /**
     * 初始化Oracle缓存
     */
    private void initializeOracleCache(String oracleName, Map<String, Object> oracleConfig) {
        oracleCache.put(oracleName, new ConcurrentHashMap<>());
        
        Map<String, Object> status = new HashMap<>();
        status.put("oracleName", oracleName);
        status.put("oracleAddress", oracleConfig.get("oracleAddress"));
        status.put("oracleStatus", "ACTIVE");
        status.put("dataCount", 0);
        status.put("lastUpdateTime", DateUtils.getNowDate());
        
        oracleStatusCache.put(oracleName, status);
        
        log.debug("Oracle缓存初始化完成: {}", oracleName);
    }
    
    /**
     * 启动数据更新任务
     */
    private void startDataUpdateTask(String oracleName, Long updateInterval) {
        updateScheduler.scheduleAtFixedRate(() -> {
            try {
                performDataUpdate(oracleName);
            } catch (Exception e) {
                log.error("Oracle数据更新任务失败: {}", oracleName, e);
            }
        }, updateInterval, updateInterval, TimeUnit.SECONDS);
        
        log.info("Oracle数据更新任务启动: {} -> interval={}s", oracleName, updateInterval);
    }
    
    /**
     * 执行数据更新
     */
    private void performDataUpdate(String oracleName) {
        log.debug("执行Oracle数据更新: {}", oracleName);
        
        // 模拟从外部数据源获取最新数据
        Map<String, Object> latestData = fetchLatestDataFromExternalSource(oracleName);
        
        if (latestData != null && !latestData.isEmpty()) {
            updateOracleData(oracleName, latestData);
            
            // 更新状态缓存
            Map<String, Object> status = oracleStatusCache.get(oracleName);
            if (status != null) {
                status.put("lastUpdateTime", DateUtils.getNowDate());
            }
        }
    }
    
    /**
     * 从外部数据源获取最新数据
     */
    private Map<String, Object> fetchLatestDataFromExternalSource(String oracleName) {
        // 模拟外部数据源
        Map<String, Object> data = new HashMap<>();
        
        switch (oracleName) {
            case "PriceOracle":
                data.put("BTC_USD", 45000 + secureRandom.nextInt(5000));
                data.put("ETH_USD", 3000 + secureRandom.nextInt(1000));
                break;
            case "InterestRateOracle":
                data.put("BASE_RATE", 3.5 + secureRandom.nextDouble() * 2);
                data.put("LENDING_RATE", 5.0 + secureRandom.nextDouble() * 3);
                break;
            case "CreditScoreOracle":
                data.put("AVERAGE_SCORE", 650 + secureRandom.nextInt(200));
                break;
            default:
                data.put("timestamp", System.currentTimeMillis());
                data.put("value", secureRandom.nextDouble() * 100);
        }
        
        data.put("signature", generateDataSignature(oracleName, "batch_update", data));
        
        return data;
    }
    
    /**
     * 解析数据值
     */
    private Object parseDataValue(String dataValue, String dataType) {
        if (dataValue == null || dataValue.trim().isEmpty()) {
            return null;
        }
        
        try {
            switch (dataType.toUpperCase()) {
                case "INTEGER":
                    return Integer.valueOf(dataValue);
                case "LONG":
                    return Long.valueOf(dataValue);
                case "DOUBLE":
                    return Double.valueOf(dataValue);
                case "BOOLEAN":
                    return Boolean.valueOf(dataValue);
                case "STRING":
                default:
                    return dataValue;
            }
        } catch (Exception e) {
            log.warn("数据值解析失败: value={}, type={}", dataValue, dataType, e);
            return dataValue;
        }
    }
    
    /**
     * 序列化数据值
     */
    private String serializeDataValue(Object dataValue, String dataType) {
        if (dataValue == null) {
            return "";
        }
        
        return dataValue.toString();
    }
    
    /**
     * 模拟外部数据源获取
     */
    private Object simulateExternalDataFetch(String oracleName, String dataKey) {
        // 模拟外部API调用
        switch (oracleName) {
            case "PriceOracle":
                if ("BTC_USD".equals(dataKey)) {
                    return 45000 + secureRandom.nextInt(5000);
                } else if ("ETH_USD".equals(dataKey)) {
                    return 3000 + secureRandom.nextInt(1000);
                }
                break;
            case "InterestRateOracle":
                if ("BASE_RATE".equals(dataKey)) {
                    return 3.5 + secureRandom.nextDouble() * 2;
                }
                break;
            case "CreditScoreOracle":
                if ("AVERAGE_SCORE".equals(dataKey)) {
                    return 650 + secureRandom.nextInt(200);
                }
                break;
        }
        
        return null;
    }
    
    /**
     * 保存Oracle数据
     */
    private void saveOracleData(String oracleName, String dataKey, Object dataValue) {
        try {
            // 获取Oracle基本信息
            List<OracleData> existingOracles = oracleDataMapper.selectOracleDataByOracleName(oracleName);
            if (existingOracles.isEmpty()) {
                throw new ServiceException("Oracle不存在: " + oracleName);
            }
            
            OracleData template = existingOracles.get(0);
            
            // 创建新的数据记录
            OracleData oracleData = new OracleData();
            oracleData.setOracleName(oracleName);
            oracleData.setOracleAddress(template.getOracleAddress());
            oracleData.setDataKey(dataKey);
            oracleData.setDataValue(serializeDataValue(dataValue, template.getDataType()));
            oracleData.setDataType(template.getDataType());
            oracleData.setDataSignature(generateDataSignature(oracleName, dataKey, dataValue));
            oracleData.setUpdateInterval(template.getUpdateInterval());
            oracleData.setLastUpdateTime(DateUtils.getNowDate());
            oracleData.setOracleStatus("ACTIVE");
            oracleData.setValidationStatus("PENDING");
            oracleData.setDescription("Oracle数据: " + dataKey);
            oracleData.setCreateTime(DateUtils.getNowDate());
            
            oracleDataMapper.insertOracleData(oracleData);
            
            log.debug("Oracle数据保存成功: {} -> {} = {}", oracleName, dataKey, dataValue);
            
        } catch (Exception e) {
            log.error("保存Oracle数据失败: {} -> {}", oracleName, dataKey, e);
        }
    }
    
    /**
     * 比较数据
     */
    private boolean compareData(Object currentData, Object expectedValue) {
        if (currentData == null && expectedValue == null) {
            return true;
        }
        
        if (currentData == null || expectedValue == null) {
            return false;
        }
        
        // 数值比较允许一定误差
        if (currentData instanceof Number && expectedValue instanceof Number) {
            double current = ((Number) currentData).doubleValue();
            double expected = ((Number) expectedValue).doubleValue();
            double tolerance = Math.abs(expected) * 0.01; // 1%误差
            return Math.abs(current - expected) <= tolerance;
        }
        
        return currentData.equals(expectedValue);
    }
    
    /**
     * 验证数据签名
     */
    private boolean verifyDataSignature(String oracleName, String dataKey, Object dataValue, String signature) {
        if (signature == null || signature.trim().isEmpty()) {
            return false;
        }
        
        try {
            String expectedSignature = generateDataSignature(oracleName, dataKey, dataValue);
            return signature.equals(expectedSignature);
        } catch (Exception e) {
            log.error("验证数据签名失败", e);
            return false;
        }
    }
    
    /**
     * 生成数据签名
     */
    private String generateDataSignature(String oracleName, String dataKey, Object dataValue) {
        try {
            String data = oracleName + ":" + dataKey + ":" + dataValue + ":" + System.currentTimeMillis();
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(data.getBytes());
            
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new ServiceException("生成数据签名失败: " + e.getMessage());
        }
    }
}