package com.aegis.camera.service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;

/**
 * 流会话管理服务
 * 用于跟踪活跃的视频流，支持空闲流清理
 *
 * @author aegis
 */
@Service
public class StreamSessionService {

    /**
     * 流会话信息：包含启动时间、最后访问时间和观看者数量
     */
    private static class StreamSessionInfo {
        final long startTime;
        volatile long lastAccessTime;
        volatile int watcherCount;

        StreamSessionInfo(long startTime) {
            this.startTime = startTime;
            this.lastAccessTime = startTime;
            this.watcherCount = 0;
        }
    }

    /**
     * 存储活跃流的映射：摄像头ID -> 流会话信息
     */
    private final Map<Long, StreamSessionInfo> activeStreams = new ConcurrentHashMap<>();

    /**
     * 注册一个活跃流
     *
     * @param cameraId 摄像头ID
     */
    public void registerStream(Long cameraId) {
        if (cameraId != null) {
            activeStreams.put(cameraId, new StreamSessionInfo(System.currentTimeMillis()));
        }
    }

    /**
     * 注销一个流（停止跟踪）
     *
     * @param cameraId 摄像头ID
     */
    public void unregisterStream(Long cameraId) {
        if (cameraId != null) {
            activeStreams.remove(cameraId);
        }
    }

    /**
     * 更新指定流的最后访问时间（心跳/活动信号）
     *
     * @param cameraId 摄像头ID
     */
    public void updateLastAccess(Long cameraId) {
        if (cameraId != null) {
            StreamSessionInfo info = activeStreams.get(cameraId);
            if (info != null) {
                info.lastAccessTime = System.currentTimeMillis();
            }
        }
    }

    /**
     * 增加观看者计数（可选，用于更精确的跟踪）
     *
     * @param cameraId 摄像头ID
     */
    public void incrementWatcher(Long cameraId) {
        if (cameraId != null) {
            StreamSessionInfo info = activeStreams.get(cameraId);
            if (info != null) {
                info.watcherCount++;
                info.lastAccessTime = System.currentTimeMillis();
            }
        }
    }

    /**
     * 减少观看者计数
     *
     * @param cameraId 摄像头ID
     */
    public void decrementWatcher(Long cameraId) {
        if (cameraId != null) {
            StreamSessionInfo info = activeStreams.get(cameraId);
            if (info != null && info.watcherCount > 0) {
                info.watcherCount--;
                info.lastAccessTime = System.currentTimeMillis();
            }
        }
    }

    /**
     * 获取空闲流列表（仅基于最后访问时间，自愈式策略）
     *
     * 策略说明：
     * 1. 仅使用 lastAccessTime 判断是否空闲，不依赖 watcherCount，避免计数不一致导致永不清理。
     * 2. 如果前端正常调用 updateLastAccess（如获取播放地址或心跳），流会保持活跃；
     * 3. 如果前端崩溃或未调用，lastAccessTime 不会更新，超时后会被自动清理（自愈）。
     *
     * @param maxIdleMs 最大空闲时间（毫秒），从最后访问时间算起
     * @return 空闲流的摄像头ID列表
     */
    public List<Long> getIdleStreams(long maxIdleMs) {
        long now = System.currentTimeMillis();
        return activeStreams.entrySet().stream()
            .filter(e -> {
                StreamSessionInfo info = e.getValue();
                long idle = now - info.lastAccessTime;
                return idle > maxIdleMs;
            })
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());
    }

    /**
     * 检查指定摄像头是否有活跃流
     *
     * @param cameraId 摄像头ID
     * @return true 如果有活跃流，false 否则
     */
    public boolean isStreamActive(Long cameraId) {
        return cameraId != null && activeStreams.containsKey(cameraId);
    }

    /**
     * 获取所有活跃流的数量
     *
     * @return 活跃流数量
     */
    public int getActiveStreamCount() {
        return activeStreams.size();
    }

    /**
     * 清除所有流记录（通常用于系统重启或维护）
     */
    public void clearAll() {
        activeStreams.clear();
    }
}