//
//  SessionTable.swift
//  Tun
//
//  Created by Codex on 2026/5/21.
//
import Foundation

actor SessionManager {
    private var sessions: [Data: [Session.AddressType: Session]] = [:]

    // session的有效时间
    private let ttl: Int32
    nonisolated private let snapshotPublisher: SnapshotPublisher<SessionSnapshot>

    init() {
        let ttl: Int32 = 10
        self.ttl = ttl
        self.snapshotPublisher = SnapshotPublisher(initial: SessionSnapshot.empty())
    }

    func getSession(toAddress: Data) -> Session? {
        let timestamp = Int32(Date().timeIntervalSince1970)

        guard var peerSessions = self.sessions[toAddress] else {
            return nil
        }

        peerSessions = peerSessions.filter { $0.value.lastTimestamp + ttl >= timestamp }
        guard !peerSessions.isEmpty else {
            self.sessions.removeValue(forKey: toAddress)
            self.publishSnapshot()
            return nil
        }

        guard var session = self.selectSession(in: peerSessions) else {
            self.sessions[toAddress] = peerSessions
            self.publishSnapshot()
            return nil
        }

        session.updateLastTimestamp(timestamp)
        peerSessions[session.addressType] = session

        self.sessions[toAddress] = peerSessions
        self.publishSnapshot()

        return session
    }

    func addSession(session: Session) {
        let timestamp = Int32(Date().timeIntervalSince1970)

        var sessions = self.sessions[session.dstMac, default: [:]]
        sessions = sessions.filter {
            $0.value.lastTimestamp + ttl >= timestamp && $0.key != session.addressType
        }
        sessions[session.addressType] = session

        self.sessions[session.dstMac] = sessions
        self.publishSnapshot()
    }

    func removeSession(dstMac: Data) {
        self.sessions.removeValue(forKey: dstMac)
        self.publishSnapshot()
    }

    func clear() {
        self.sessions.removeAll()
        self.publishSnapshot()
    }

    nonisolated func snapshot() -> SessionSnapshot {
        return self.snapshotPublisher.current()
    }

    private func selectSession(in sessions: [Session.AddressType: Session]) -> Session? {
        return sessions.values.max(by: { $0.lastTimestamp < $1.lastTimestamp })
    }

    private func publishSnapshot() {
        self.snapshotPublisher.publish(self.compileSnapshot())
    }

    private func compileSnapshot() -> SessionSnapshot {
        let timestamp = Int32(Date().timeIntervalSince1970)
        let sessions = self.sessions.compactMapValues { peerSessions in
            let validSessions = peerSessions.filter { $0.value.lastTimestamp + self.ttl >= timestamp }
            return validSessions.isEmpty ? nil : validSessions
        }
        return SessionSnapshot(sessions: sessions)
    }
}
