package com.gameplatform.server.service.device;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gameplatform.server.model.dto.device.DeviceStatusResponse;
import com.gameplatform.server.service.admin.SystemConfigService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 设备状态服务
 */
@Service
public class DeviceStatusService {
    private static final Logger log = LoggerFactory.getLogger(DeviceStatusService.class);
    
    private final ObjectMapper objectMapper;
    private final SystemConfigService systemConfigService;
    
    // 设备编号解析正则
    private static final Pattern DEVICE_PATTERN = Pattern.compile("^(f|s|g|d|ss|gg)(\\d+)$");
    
    public DeviceStatusService(ObjectMapper objectMapper, SystemConfigService systemConfigService) {
        this.objectMapper = objectMapper;
        this.systemConfigService = systemConfigService;
    }
    
    /**
     * 解析设备状态JSON响应
     */
    public DeviceStatusResponse parseDeviceStatus(String jsonResponse) {
        try {
            log.debug("开始解析设备状态响应");
            
            JsonNode rootNode = objectMapper.readTree(jsonResponse);
            Map<String, DeviceStatusResponse.DeviceInfo> devices = new HashMap<>();
            List<String> availableDevices = new ArrayList<>();
            
            // 遍历所有设备
            Iterator<Map.Entry<String, JsonNode>> fields = rootNode.fields();
            while (fields.hasNext()) {
                Map.Entry<String, JsonNode> field = fields.next();
                String deviceId = field.getKey();
                JsonNode deviceNode = field.getValue();
                
                // 解析设备信息
                DeviceStatusResponse.DeviceInfo deviceInfo = parseDeviceInfo(deviceId, deviceNode);
                devices.put(deviceId, deviceInfo);
                
                // 检查是否空闲
                if (deviceInfo.isAvailable()) {
                    availableDevices.add(deviceId);
                }
            }
            
            // 构建响应
            DeviceStatusResponse response = new DeviceStatusResponse();
            response.setDevices(devices);
            response.setAvailableDevices(availableDevices);
            response.setTotalDevices(devices.size());
            response.setAvailableCount(availableDevices.size());
            
            log.info("设备状态解析完成: 总设备数={}, 空闲设备数={}, 空闲设备={}", 
                    response.getTotalDevices(), response.getAvailableCount(), availableDevices);
            
            return response;
            
        } catch (JsonProcessingException e) {
            log.error("解析设备状态JSON失败: {}", e.getMessage(), e);
            throw new RuntimeException("解析设备状态失败", e);
        }
    }
    
    /**
     * 解析单个设备信息
     */
    private DeviceStatusResponse.DeviceInfo parseDeviceInfo(String deviceId, JsonNode deviceNode) {
        DeviceStatusResponse.DeviceInfo deviceInfo = new DeviceStatusResponse.DeviceInfo();
        deviceInfo.setDeviceId(deviceId);
        
        // 解析val和time
        String val = deviceNode.get("val").asText();
        String time = deviceNode.get("time").asText();
        deviceInfo.setVal(val);
        deviceInfo.setTime(time);
        
        // 解析设备系列和序号
        parseDeviceIdComponents(deviceId, deviceInfo);
        
        // 判断是否空闲
        boolean available = isDeviceAvailable(val);
        deviceInfo.setAvailable(available);
        
        log.debug("解析设备信息: deviceId={}, val={}, time={}, available={}, series={}, index={}", 
                deviceId, val, time, available, deviceInfo.getSeries(), deviceInfo.getIndex());
        
        return deviceInfo;
    }
    
    /**
     * 解析设备编号的组成部分
     */
    private void parseDeviceIdComponents(String deviceId, DeviceStatusResponse.DeviceInfo deviceInfo) {
        Matcher matcher = DEVICE_PATTERN.matcher(deviceId);
        if (matcher.matches()) {
            String series = matcher.group(1);
            String indexStr = matcher.group(2);
            
            deviceInfo.setSeries(series);
            try {
                deviceInfo.setIndex(Integer.parseInt(indexStr));
            } catch (NumberFormatException e) {
                log.warn("解析设备序号失败: deviceId={}, indexStr={}", deviceId, indexStr);
                deviceInfo.setIndex(null);
            }
        } else {
            deviceInfo.setSeries(null);
            deviceInfo.setIndex(null);
        }
    }
    
    /**
     * 判断设备是否空闲
     */
    private boolean isDeviceAvailable(String val) {
        String idleStatus = systemConfigService.getDeviceIdleStatus();
        return idleStatus.equals(val);
    }

    /**
     * 解析特定设备的状态信息（用于检查是否完成游戏）
     * @param jsonResponse JSON响应字符串
     * @param machineId 设备ID
     * @return 包含f0(点数)和f1(状态)的Map
     */
    public Map<String, Object> parseDeviceStatusForMachine(String jsonResponse, String machineId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            log.debug("解析设备 {} 的状态信息", machineId);
            
            JsonNode rootNode = objectMapper.readTree(jsonResponse);
            
            // 查找指定设备的信息
            JsonNode deviceNode = rootNode.get(machineId);
            if (deviceNode == null) {
                log.warn("未找到设备 {} 的状态信息", machineId);
                return result;
            }
            
            // 解析f0(点数)和f1(状态)等信息
            String val = deviceNode.get("val").asText();
            String time = deviceNode.get("time").asText();
            
            // 构建f0和f1格式的返回数据
            Map<String, Object> f0Info = new HashMap<>();
            Map<String, Object> f1Info = new HashMap<>();
            
            // 假设val包含点数信息，f1包含状态信息
            // 根据实际API响应格式调整
            if (val.matches("\\d+")) {
                // 如果val是数字，则认为是点数
                f0Info.put("val", val);
                f0Info.put("time", time);
                result.put("f0", f0Info);
                
                // 状态信息需要额外获取，这里先设置默认值
                String idleStatus = systemConfigService.getDeviceIdleStatus();
                f1Info.put("val", idleStatus); // 如果能获取到点数，可能表示空闲
                f1Info.put("time", time);
                result.put("f1", f1Info);
            } else {
                // 如果val不是数字，可能是状态信息
                f1Info.put("val", val);
                f1Info.put("time", time);
                result.put("f1", f1Info);
            }
            
            log.debug("设备 {} 状态解析完成: {}", machineId, result);
            
        } catch (JsonProcessingException e) {
            log.error("解析设备 {} 状态JSON失败: {}", machineId, e.getMessage(), e);
        } catch (Exception e) {
            log.error("解析设备 {} 状态时发生异常", machineId, e);
        }
        
        return result;
    }
    
    /**
     * 按系列分组空闲设备
     */
    public Map<String, List<String>> groupAvailableDevicesBySeries(DeviceStatusResponse deviceStatus) {
        Map<String, List<String>> groupedDevices = new HashMap<>();
        
        for (String deviceId : deviceStatus.getAvailableDevices()) {
            DeviceStatusResponse.DeviceInfo deviceInfo = deviceStatus.getDevices().get(deviceId);
            if (deviceInfo != null && deviceInfo.getSeries() != null) {
                String series = deviceInfo.getSeries();
                groupedDevices.computeIfAbsent(series, k -> new ArrayList<>()).add(deviceId);
            }
        }
        
        return groupedDevices;
    }
    
    /**
     * 获取指定系列的空闲设备
     */
    public List<String> getAvailableDevicesBySeries(DeviceStatusResponse deviceStatus, String series) {
        return deviceStatus.getAvailableDevices().stream()
                .filter(deviceId -> {
                    DeviceStatusResponse.DeviceInfo deviceInfo = deviceStatus.getDevices().get(deviceId);
                    return deviceInfo != null && series.equals(deviceInfo.getSeries());
                })
                .sorted() // 按设备编号排序
                .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
    }
}
