package com.ycwl.basic.repository;

import com.ycwl.basic.integration.device.service.DeviceConfigIntegrationService;
import com.ycwl.basic.integration.device.dto.config.DeviceConfigV2DTO;
import com.ycwl.basic.utils.JacksonUtil;
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
import com.ycwl.basic.utils.SnowFlakeUtil;
import com.ycwl.basic.integration.device.service.DeviceIntegrationService;
import com.ycwl.basic.integration.device.service.DeviceStatusIntegrationService;
import com.ycwl.basic.integration.device.dto.device.DeviceV2DTO;
import com.ycwl.basic.integration.device.dto.status.DeviceStatusDTO;
import com.ycwl.basic.integration.common.manager.DeviceConfigManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;

import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class DeviceRepository {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private DeviceIntegrationService deviceIntegrationService;

    public static final String DEVICE_ONLINE_CACHE_KEY = "device:online_status:%s";
    public static final String DEVICE_CACHE_KEY = "device:%s";
    @Autowired
    private DeviceConfigIntegrationService deviceConfigIntegrationService;
    @Autowired
    private DeviceStatusIntegrationService deviceStatusIntegrationService;

    /**
     * 将DeviceV2DTO转换为DeviceEntity
     */
    private DeviceEntity convertToEntity(DeviceV2DTO dto) {
        if (dto == null) {
            return null;
        }
        DeviceEntity entity = new DeviceEntity();
        entity.setId(dto.getId());
        entity.setName(dto.getName());
        entity.setNo(dto.getNo());
        entity.setScenicId(dto.getScenicId());
        // DeviceV2DTO中的isActive对应DeviceEntity中的status
        entity.setStatus(dto.getIsActive());
        if (dto.getCreateTime() != null) {
            entity.setCreateAt(dto.getCreateTime());
        }
        if (dto.getUpdateTime() != null) {
            entity.setUpdateAt(dto.getUpdateTime());
        }
        return entity;
    }

    /**
     * 将DeviceV2DTO和DeviceStatusDTO合并转换为DeviceEntity
     */
    private DeviceEntity convertToEntityWithStatus(DeviceV2DTO deviceDto, DeviceStatusDTO statusDto) {
        if (deviceDto == null) {
            return null;
        }
        
        DeviceEntity entity = convertToEntity(deviceDto);
        
        // 合并状态信息
        if (statusDto != null) {
            // Boolean转Integer: true→1, false→0
            entity.setOnline(statusDto.getIsOnline() != null && statusDto.getIsOnline() ? 1 : 0);
            // 添加空值检查，避免NullPointerException
            if (statusDto.getLastActiveTime() != null) {
                entity.setKeepaliveAt(statusDto.getLastActiveTime());
            }
            if (statusDto.getClientIP() != null) {
                entity.setIpAddr(statusDto.getClientIP());
            }
        } else {
            // 默认离线状态
            entity.setOnline(0);
        }
        
        return entity;
    }

    public DeviceEntity getDevice(Long deviceId) {
        log.debug("获取设备信息, deviceId: {}", deviceId);
        DeviceV2DTO deviceDto = deviceIntegrationService.getDevice(deviceId);
        DeviceEntity device = convertToEntity(deviceDto);
        return device;
    }

    /**
     * 获取设备基本信息（直接返回DeviceV2DTO）
     *
     * @param deviceId 设备ID
     * @return DeviceV2DTO实例
     */
    public DeviceV2DTO getDeviceBasic(Long deviceId) {
        log.debug("获取设备基本信息, deviceId: {}", deviceId);
        return deviceIntegrationService.getDevice(deviceId);
    }

    public DeviceEntity getDeviceByDeviceNo(String deviceNo) {
        log.debug("根据设备编号获取设备信息, deviceNo: {}", deviceNo);
        DeviceV2DTO deviceDto = deviceIntegrationService.getDeviceByNo(deviceNo);
        DeviceEntity device = convertToEntity(deviceDto);
        return device;
    }

    public DeviceConfigEntity getDeviceConfig(Long deviceId) {
        DeviceConfigManager configManager = getDeviceConfigManager(deviceId);
        if (configManager != null) {
            return convertToDeviceConfigEntity(configManager, deviceId);
        }
        return null;
    }

    /**
     * 获取设备配置管理器
     * 
     * @param deviceId 设备ID
     * @return DeviceConfigManager实例，如果获取失败返回null
     */
    public DeviceConfigManager getDeviceConfigManager(Long deviceId) {
        try {
            List<DeviceConfigV2DTO> configList = deviceConfigIntegrationService.getDeviceConfigs(deviceId);
            return new DeviceConfigManager(configList);
        } catch (Exception e) {
            log.warn("获取设备配置管理器失败, deviceId: {}", deviceId, e);
            return null;
        }
    }

    /**
     * 将DeviceConfigV2DTO列表转换为DeviceConfigEntity（为了兼容性）
     */
    private DeviceConfigEntity convertToDeviceConfigEntity(DeviceConfigManager configManager, Long deviceId) {
        DeviceConfigEntity entity = new DeviceConfigEntity();
        entity.setId(SnowFlakeUtil.getLongId());
        entity.setDeviceId(deviceId);
        
        // 通过configManager获取对应的字段写入到deviceConfigEntity中
        entity.setViidType(configManager.getInteger("viid_type"));
        entity.setStoreType(configManager.getInteger("store_type"));
        entity.setStoreConfigJson(configManager.getString("store_config_json"));
        entity.setStoreExpireDay(configManager.getInteger("store_expire_day"));
        entity.setOnlineCheck(configManager.getInteger("online_check"));
        entity.setOnlineMaxInterval(configManager.getInteger("online_max_interval"));
        entity.setCutPre(configManager.getBigDecimal("cut_pre"));
        entity.setCutPost(configManager.getBigDecimal("cut_post"));
        entity.setEnablePreBook(configManager.getInteger("enable_pre_book"));
        entity.setImageFree(configManager.getInteger("image_free"));
        entity.setVideoFree(configManager.getInteger("video_free"));
        entity.setPairDevice(configManager.getLong("pair_device"));
        entity.setVideoCrop(configManager.getString("video_crop"));
        entity.setCropConfig(configManager.getString("crop_config"));
        
        return entity;
    }

    public void updateOnlineStatus(String deviceNo, int online, Date keepaliveAt) {
        DeviceEntity device = getDeviceByDeviceNo(deviceNo);
        if (null == device) {
            return;
        }
        updateOnlineStatus(device.getId(), null, online, keepaliveAt);
    }

    public void updateOnlineStatus(Long deviceId, String ipAddr, int online, Date keepaliveAt) {
        DeviceEntity device = getDevice(deviceId);
        if (null == device) {
            return;
        }
        device.setOnline(online);
        device.setKeepaliveAt(keepaliveAt);
        device.setIpAddr(ipAddr);
        redisTemplate.opsForValue().set(String.format(DEVICE_ONLINE_CACHE_KEY, deviceId), JacksonUtil.toJSONString(device), 3, TimeUnit.DAYS);
//        deviceMapper.updateOnlineStatus(deviceId, ipAddr, online, keepaliveAt);
        updateDeviceCache(device);
    }

    public DeviceEntity getOnlineStatus(Long deviceId) {
        log.debug("获取设备在线状态, deviceId: {}", deviceId);
        try {
            // 首先获取设备基本信息
            DeviceV2DTO deviceDto = deviceIntegrationService.getDevice(deviceId);
            if (deviceDto == null) {
                log.warn("设备不存在, deviceId: {}", deviceId);
                return null;
            }
            
            // 通过设备编号获取设备状态
            DeviceStatusDTO statusDto = deviceStatusIntegrationService.getDeviceStatus(deviceDto.getNo());
            
            // 合并设备信息和状态信息
            return convertToEntityWithStatus(deviceDto, statusDto);
            
        } catch (Exception e) {
            log.error("获取设备在线状态异常, deviceId: {}", deviceId, e);
            // 降级处理：尝试仅返回设备基本信息
            try {
                DeviceV2DTO deviceDto = deviceIntegrationService.getDevice(deviceId);
                return convertToEntityWithStatus(deviceDto, null);
            } catch (Exception fallbackException) {
                log.error("降级获取设备信息也失败, deviceId: {}", deviceId, fallbackException);
                return null;
            }
        }
    }

    private void updateDeviceCache(DeviceEntity device) {
        redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, device.getId()), JacksonUtil.toJSONString(device));
        redisTemplate.opsForValue().set(String.format(DEVICE_CACHE_KEY, device.getNo()), JacksonUtil.toJSONString(device));
    }

    public List<DeviceV2DTO> getAllDeviceByScenicId(Long scenicId) {
        try {
            var deviceListResponse = deviceIntegrationService.getScenicActiveDevices(scenicId, 1, 1000);
            if (deviceListResponse != null && deviceListResponse.getList() != null) {
                return deviceListResponse.getList();
            }
        } catch (Exception e) {
            log.warn("获取景区设备列表失败，景区ID: {}, 错误: {}", scenicId, e.getMessage());
        }
        return List.of();
    }

    /**
     * 批量获取设备信息
     * @param deviceIds 设备ID列表
     * @return 设备ID到设备实体的映射
     */
    public Map<Long, DeviceEntity> batchGetDevices(List<Long> deviceIds) {
        if (deviceIds == null || deviceIds.isEmpty()) {
            return new HashMap<>();
        }
        
        Map<Long, DeviceEntity> result = new HashMap<>();
        for (Long deviceId : deviceIds) {
            try {
                DeviceEntity device = getDevice(deviceId);
                if (device != null) {
                    result.put(deviceId, device);
                }
            } catch (Exception e) {
                log.warn("获取设备信息失败: {}, 错误: {}", deviceId, e.getMessage());
            }
        }
        return result;
    }

    /**
     * 批量根据设备编号获取设备信息
     * @param deviceNos 设备编号列表
     * @return 设备编号到设备实体的映射
     */
    public Map<String, DeviceEntity> batchGetDevicesByNo(List<String> deviceNos) {
        if (deviceNos == null || deviceNos.isEmpty()) {
            return new HashMap<>();
        }
        
        Map<String, DeviceEntity> result = new HashMap<>();
        for (String deviceNo : deviceNos) {
            try {
                DeviceEntity device = getDeviceByDeviceNo(deviceNo);
                if (device != null) {
                    result.put(deviceNo, device);
                }
            } catch (Exception e) {
                log.warn("根据设备编号获取设备信息失败: {}, 错误: {}", deviceNo, e.getMessage());
            }
        }
        return result;
    }

    /**
     * 批量获取设备名称
     * @param deviceIds 设备ID列表
     * @return 设备ID到设备名称的映射
     */
    public Map<Long, String> batchGetDeviceNames(List<Long> deviceIds) {
        if (deviceIds == null || deviceIds.isEmpty()) {
            return new HashMap<>();
        }
        
        Map<Long, String> result = new HashMap<>();
        for (Long deviceId : deviceIds) {
            try {
                DeviceEntity device = getDevice(deviceId);
                if (device != null) {
                    result.put(deviceId, device.getName());
                }
            } catch (Exception e) {
                log.warn("获取设备名称失败: {}, 错误: {}", deviceId, e.getMessage());
                result.put(deviceId, "未知设备");
            }
        }
        return result;
    }
}
