package com.ycwl.basic.integration.device.service;

import com.ycwl.basic.integration.common.exception.IntegrationException;
import com.ycwl.basic.integration.common.response.CommonResponse;
import com.ycwl.basic.integration.common.response.PageResponse;
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
import com.ycwl.basic.integration.device.client.DeviceV2Client;
import com.ycwl.basic.integration.device.dto.defaults.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Map;

/**
 * 默认配置集成服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DeviceDefaultConfigIntegrationService {

    private final DeviceV2Client defaultConfigClient;
    private final IntegrationFallbackService fallbackService;
    
    private static final String SERVICE_NAME = "zt-device";

    /**
     * 获取默认配置列表（支持 Fallback）
     */
    public PageResponse<DefaultConfigResponse> listDefaultConfigs(int page, int pageSize) {
        return fallbackService.executeWithFallback(
            SERVICE_NAME,
            "defaults:list:" + page + ":" + pageSize,
            () -> {
                CommonResponse<PageResponse<DefaultConfigResponse>> response = defaultConfigClient.listDefaultConfigs(page, pageSize);
                return handleResponse(response, "获取默认配置列表失败");
            },
            PageResponse.class
        );
    }

    /**
     * 根据配置键获取默认配置（支持 Fallback）
     */
    public DefaultConfigResponse getDefaultConfig(String configKey) {
        return fallbackService.executeWithFallback(
            SERVICE_NAME,
            "defaults:config:" + configKey,
            () -> {
                log.info("获取默认配置, configKey: {}", configKey);
                CommonResponse<DefaultConfigResponse> response = defaultConfigClient.getDefaultConfig(configKey);
                return handleResponse(response, "获取默认配置失败");
            },
            DefaultConfigResponse.class
        );
    }

    /**
     * 创建默认配置（直接操作，不支持 Fallback）
     */
    public boolean createDefaultConfig(DefaultConfigRequest request) {
        log.info("创建默认配置, configKey: {}", request.getConfigKey());
        CommonResponse<String> response = defaultConfigClient.createDefaultConfig(request);
        String result = handleResponse(response, "创建默认配置失败");
        // 清理相关缓存
        clearDefaultConfigCache(request.getConfigKey());
        return result != null;
    }

    /**
     * 更新默认配置（直接操作，不支持 Fallback）
     */
    public DefaultConfigConflict updateDefaultConfig(String configKey, Map<String, Object> updates) {
        log.info("更新默认配置, configKey: {}, updates: {}", configKey, updates);
        CommonResponse<Map<String, Object>> response = defaultConfigClient.updateDefaultConfig(configKey, updates);
        Map<String, Object> result = handleResponse(response, "更新默认配置失败");
        
        // 清理相关缓存
        clearDefaultConfigCache(configKey);
        
        // 检查是否有冲突信息
        if (result != null && result.containsKey("conflict")) {
            Object conflictObj = result.get("conflict");
            if (conflictObj instanceof Map) {
                // 将Map转换为DefaultConfigConflict对象
                return mapToDefaultConfigConflict((Map<String, Object>) conflictObj);
            }
        }
        
        return null;
    }

    /**
     * 删除默认配置（直接操作，不支持 Fallback）
     */
    public boolean deleteDefaultConfig(String configKey) {
        log.info("删除默认配置, configKey: {}", configKey);
        CommonResponse<String> response = defaultConfigClient.deleteDefaultConfig(configKey);
        String result = handleResponse(response, "删除默认配置失败");
        // 清理相关缓存
        clearDefaultConfigCache(configKey);
        return result != null;
    }

    /**
     * 批量更新默认配置（直接操作，不支持 Fallback）
     */
    public BatchDefaultConfigResponse batchUpdateDefaultConfigs(BatchDefaultConfigRequest request) {
        log.info("批量更新默认配置, configs count: {}", request.getConfigs().size());
        CommonResponse<BatchDefaultConfigResponse> response = defaultConfigClient.batchUpdateDefaultConfigs(request);
        BatchDefaultConfigResponse result = handleResponse(response, "批量更新默认配置失败");
        // 清理所有默认配置相关缓存
        clearAllDefaultConfigCache();
        return result;
    }

    /**
     * 清理指定配置的缓存
     */
    private void clearDefaultConfigCache(String configKey) {
        if (configKey != null) {
            fallbackService.clearFallbackCache(SERVICE_NAME, "defaults:config:" + configKey);
        }
    }

    /**
     * 清理所有默认配置缓存
     */
    private void clearAllDefaultConfigCache() {
        fallbackService.clearAllFallbackCache(SERVICE_NAME);
    }

    /**
     * 创建批量配置请求构建器
     */
    public BatchDefaultConfigRequestBuilder createBatchConfigBuilder() {
        return new BatchDefaultConfigRequestBuilder();
    }
    
    /**
     * 批量配置请求构建器
     */
    public static class BatchDefaultConfigRequestBuilder {
        private final BatchDefaultConfigRequest request = new BatchDefaultConfigRequest();
        
        public BatchDefaultConfigRequestBuilder() {
            request.setConfigs(new ArrayList<>());
        }
        
        /**
         * 添加配置项
         */
        public BatchDefaultConfigRequestBuilder addConfig(String configKey, String configValue, 
                                                        String configType, String description) {
            DefaultConfigRequest item = new DefaultConfigRequest();
            item.setConfigKey(configKey);
            item.setConfigValue(configValue);
            item.setConfigType(configType);
            item.setDescription(description);
            request.getConfigs().add(item);
            return this;
        }
        
        /**
         * 添加视频配置
         */
        public BatchDefaultConfigRequestBuilder addVideoConfig(String resolution, Integer frameRate, String codec) {
            addConfig("resolution", resolution, "string", "视频分辨率");
            addConfig("frameRate", frameRate.toString(), "int", "视频帧率");
            addConfig("codec", codec, "string", "视频编码格式");
            return this;
        }
        
        /**
         * 添加网络配置
         */
        public BatchDefaultConfigRequestBuilder addNetworkConfig(String ipAddress, Integer port, String protocol) {
            addConfig("ipAddress", ipAddress, "string", "IP地址");
            addConfig("port", port.toString(), "int", "端口号");
            addConfig("protocol", protocol, "string", "网络协议");
            return this;
        }
        
        /**
         * 构建请求对象
         */
        public BatchDefaultConfigRequest build() {
            return request;
        }
    }

    /**
     * 将Map转换为DefaultConfigConflict对象
     */
    @SuppressWarnings("unchecked")
    private DefaultConfigConflict mapToDefaultConfigConflict(Map<String, Object> map) {
        DefaultConfigConflict conflict = new DefaultConfigConflict();
        
        if (map.containsKey("configKey")) {
            conflict.setConfigKey((String) map.get("configKey"));
        }
        if (map.containsKey("conflictType")) {
            conflict.setConflictType((String) map.get("conflictType"));
        }
        if (map.containsKey("deviceCount")) {
            Object deviceCount = map.get("deviceCount");
            if (deviceCount instanceof Number) {
                conflict.setDeviceCount(((Number) deviceCount).intValue());
            }
        }
        if (map.containsKey("currentType")) {
            conflict.setCurrentType((String) map.get("currentType"));
        }
        if (map.containsKey("proposedType")) {
            conflict.setProposedType((String) map.get("proposedType"));
        }
        if (map.containsKey("conflictDevices")) {
            Object conflictDevices = map.get("conflictDevices");
            if (conflictDevices instanceof Iterable) {
                conflict.setConflictDevices(new ArrayList<>());
                for (Object deviceId : (Iterable<?>) conflictDevices) {
                    if (deviceId instanceof Number) {
                        conflict.getConflictDevices().add(((Number) deviceId).longValue());
                    }
                }
            }
        }
        
        return conflict;
    }

    private <T> T handleResponse(CommonResponse<T> response, String errorMessage) {
        if (response == null || !response.isSuccess()) {
            String msg = response != null && response.getMessage() != null 
                        ? response.getMessage() 
                        : errorMessage;
            Integer code = response != null ? response.getCode() : 5000;
            throw new IntegrationException(code, msg, SERVICE_NAME);
        }
        return response.getData();
    }
}