package com.ycwl.basic.controller.pc;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ycwl.basic.annotation.IgnoreToken;
import com.ycwl.basic.device.entity.common.DeviceVideoContinuityCache;
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
import com.ycwl.basic.model.pc.device.req.VideoContinuityReportReq;
import com.ycwl.basic.repository.DeviceRepository;
import com.ycwl.basic.utils.ApiResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 设备视频连续性检查控制器
 * 提供查询设备视频连续性检查结果的接口
 *
 * @author Claude Code
 * @date 2025-09-01
 */
@Slf4j
@RestController
@RequestMapping("/api/device/video-continuity")
@RequiredArgsConstructor
public class DeviceVideoContinuityController {

    private static final String REDIS_KEY_PREFIX = "device:video:continuity:";
    private static final int CACHE_TTL_HOURS = 24; // 缓存24小时

    private final RedisTemplate<String, String> redisTemplate;
    private final ObjectMapper objectMapper;
    private final DeviceRepository deviceRepository;

    /**
     * 查询设备最近的视频连续性检查结果
     *
     * @param deviceId 设备ID
     * @return 检查结果
     */
    @GetMapping("/{deviceId}")
    public ApiResponse<DeviceVideoContinuityCache> getDeviceContinuityResult(@PathVariable Long deviceId) {
        log.info("查询设备 {} 的视频连续性检查结果", deviceId);

        try {
            String redisKey = REDIS_KEY_PREFIX + deviceId;
            String cacheJson = redisTemplate.opsForValue().get(redisKey);

            if (cacheJson == null) {
                log.warn("未找到设备 {} 的视频连续性检查结果", deviceId);
                return ApiResponse.buildResponse(404, null, "未找到该设备的检查结果,可能设备未配置存储或尚未执行检查");
            }

            DeviceVideoContinuityCache cache = objectMapper.readValue(cacheJson, DeviceVideoContinuityCache.class);
            return ApiResponse.success(cache);

        } catch (Exception e) {
            log.error("查询设备 {} 视频连续性检查结果失败", deviceId, e);
            return ApiResponse.buildResponse(500, null, "查询失败: " + e.getMessage());
        }
    }

    /**
     * 手动触发设备视频连续性检查
     * 注意：仅用于测试和紧急情况,正常情况下由定时任务自动执行
     *
     * @param deviceId 设备ID
     * @return 检查结果
     */
    @PostMapping("/{deviceId}/check")
    public ApiResponse<DeviceVideoContinuityCache> manualCheck(@PathVariable Long deviceId) {
        log.info("手动触发设备 {} 的视频连续性检查", deviceId);
        return ApiResponse.success(null);
    }

    /**
     * 删除设备的视频连续性检查缓存
     * 用于清理过期或错误的缓存数据
     *
     * @param deviceId 设备ID
     * @return 删除结果
     */
    @DeleteMapping("/{deviceId}")
    public ApiResponse<String> deleteContinuityCache(@PathVariable Long deviceId) {
        log.info("删除设备 {} 的视频连续性检查缓存", deviceId);

        try {
            String redisKey = REDIS_KEY_PREFIX + deviceId;
            Boolean deleted = redisTemplate.delete(redisKey);

            if (deleted != null && deleted) {
                return ApiResponse.success("缓存删除成功");
            } else {
                return ApiResponse.buildResponse(404, null, "未找到该设备的缓存数据");
            }

        } catch (Exception e) {
            log.error("删除设备 {} 视频连续性检查缓存失败", deviceId, e);
            return ApiResponse.buildResponse(500, null, "删除失败: " + e.getMessage());
        }
    }

    /**
     * 外部工具上报视频连续性检查结果
     * 通过设备编号(deviceNo)上报检查结果，无需认证
     *
     * @param reportReq 上报请求
     * @return 上报结果
     */
    @PostMapping("/report")
    @IgnoreToken
    public ApiResponse<DeviceVideoContinuityCache> reportContinuityResult(
            @Validated @RequestBody VideoContinuityReportReq reportReq) {
        log.info("外部工具上报设备 {} 的视频连续性检查结果", reportReq.getDeviceNo());

        try {
            // 1. 根据设备编号查询设备ID
            DeviceEntity device = deviceRepository.getDeviceByDeviceNo(reportReq.getDeviceNo());
            if (device == null) {
                log.warn("设备编号 {} 不存在", reportReq.getDeviceNo());
                return ApiResponse.buildResponse(404, null, "设备不存在: " + reportReq.getDeviceNo());
            }

            Long deviceId = device.getId();

            // 2. 构建缓存对象
            DeviceVideoContinuityCache cache = new DeviceVideoContinuityCache();
            cache.setDeviceId(deviceId);
            cache.setCheckTime(new Date());
            cache.setStartTime(reportReq.getStartTime());
            cache.setEndTime(reportReq.getEndTime());
            cache.setSupport(reportReq.getSupport());
            cache.setContinuous(reportReq.getContinuous());
            cache.setTotalVideos(reportReq.getTotalVideos());
            cache.setTotalDurationMs(reportReq.getTotalDurationMs());
            cache.setMaxAllowedGapMs(reportReq.getMaxAllowedGapMs() != null
                    ? reportReq.getMaxAllowedGapMs() : 2000L);
            cache.setGapCount(reportReq.getGaps() != null ? reportReq.getGaps().size() : 0);

            // 3. 转换间隙信息
            if (reportReq.getGaps() != null && !reportReq.getGaps().isEmpty()) {
                List<DeviceVideoContinuityCache.GapInfo> gapInfos = reportReq.getGaps().stream()
                        .map(gap -> new DeviceVideoContinuityCache.GapInfo(
                                gap.getBeforeFileName(),
                                gap.getAfterFileName(),
                                gap.getGapMs(),
                                gap.getGapStartTime(),
                                gap.getGapEndTime()
                        ))
                        .collect(Collectors.toList());
                cache.setGaps(gapInfos);
            }

            // 4. 存储到Redis
            String redisKey = REDIS_KEY_PREFIX + deviceId;
            String cacheJson = objectMapper.writeValueAsString(cache);
            redisTemplate.opsForValue().set(redisKey, cacheJson, CACHE_TTL_HOURS, TimeUnit.HOURS);

            log.info("设备 {} (ID: {}) 视频连续性检查结果上报成功: continuous={}, videos={}, gaps={}",
                    reportReq.getDeviceNo(), deviceId, cache.getContinuous(),
                    cache.getTotalVideos(), cache.getGapCount());

            return ApiResponse.success(cache);

        } catch (Exception e) {
            log.error("外部工具上报设备 {} 视频连续性检查结果失败", reportReq.getDeviceNo(), e);
            return ApiResponse.buildResponse(500, null, "上报失败: " + e.getMessage());
        }
    }
}
