//
//  PolicyService.swift
//  punchnet
//
//  Created by 安礼成 on 2026/5/19.
//

import Foundation

actor PolicyService {
    // 处理权限控制
    private let policyRuleStore: PolicyRuleStore
    nonisolated private let snapshotPublisher: SnapshotPublisher<PolicyRuleSnapshot>
    
    // Flow流会话管理， 过期时间为: 180秒
    nonisolated private let flowSessionTable = FlowSessionTable(sessionTimeout: 180)
    
    // 当前节点的identityId值
    let identityId: UInt32
    
    init(identityId: UInt32) {
        self.identityId = identityId
        // 权限控制
        let snapshotPublisher = SnapshotPublisher(initial: PolicyRuleSnapshot.empty())
        self.policyRuleStore = PolicyRuleStore(publisher: snapshotPublisher)
        self.snapshotPublisher = snapshotPublisher
    }
    
    nonisolated func policyRuntime() -> PolicyRuntime {
        return PolicyRuntime(policyRuleSnapshot: self.snapshotPublisher.current(), flowSessionTable: self.flowSessionTable)
    }

    nonisolated func recordOutboundFlow(ipPacket: IPPacketView) {
        guard let flowSession = ipPacket.flowSession() else {
            return
        }

        self.flowSessionTable.updateSession(flowSession)
    }

    func makePolicyRequest(srcIdentityID: UInt32) async -> Data? {
        return await self.policyRuleStore.makePolicyRequest(srcIdentityId: srcIdentityID, dstIdentityId: self.identityId)
    }
    
    func updatePolicy(superServiceProxy: SDLSuperServiceProxy) async {
        let requests = await self.policyRuleStore.makeBatchPolicyRequests(dstIdentityID: self.identityId)
        for request in requests {
            await superServiceProxy.send(type: .policyRequest, data: request)
        }
    }

    func applyPolicyResponse(_ policyResponse: SDLPolicyResponse) async {
        guard policyResponse.dstIdentityID == self.identityId else {
            SDLLogger.log("[PolicyService] ignore policy response, dstIdentityID mismatch: \(policyResponse.dstIdentityID), expected: \(self.identityId)", for: .debug)
            return
        }

        await self.policyRuleStore.applyPolicyResponse(policyResponse)
    }
    
    func clear() async {
        self.flowSessionTable.clear()
        await self.policyRuleStore.clear()
    }
    
    deinit {
        SDLLogger.log("[PolicyService] deinit")
    }
    
}
