//
//  SDLSuperEventProcessor.swift
//  Tun
//
//  Created by 安礼成 on 2026/4/15.
//

import Foundation
import NIOCore

final class SDLSuperEventProcessor {
    enum ProcessingAction {
        case removeSession(dstMac: Data)
        case sendRegister(data: Data, remoteAddresses: [SocketAddress])
        case shutdown(message: String)
        case none
    }
    
    struct ProcessingPlan {
        let logMessage: String?
        let action: ProcessingAction
    }
    
    private let networkAddress: SDLConfiguration.NetworkAddress
    
    init(networkAddress: SDLConfiguration.NetworkAddress) {
        self.networkAddress = networkAddress
    }
    
    func makeProcessingPlan(event: SDLEvent) async -> ProcessingPlan {
        switch event.event {
        case .natChanged(let natChangedEvent):
            let dstMac = natChangedEvent.mac
            return .init(
                logMessage: "[SDLContext] natChangedEvent, dstMac: \(dstMac)",
                action: .removeSession(dstMac: dstMac)
            )
        case .sendRegister(let sendRegisterEvent):
            return await self.makeSendRegisterPlan(sendRegisterEvent)
        case .shutdown(let shutdownEvent):
            return .init(logMessage: nil, action: .shutdown(message: shutdownEvent.message))
        case .none:
            return .init(logMessage: nil, action: .none)
        }
    }
    
    private func makeSendRegisterPlan(_ event: SDLEvent.SendRegister) async -> ProcessingPlan {
        // 发送register包
        var register = SDLRegister()
        register.networkID = self.networkAddress.networkId
        register.srcMac = self.networkAddress.mac
        register.dstMac = event.dstMac
        let registerData = try! register.serializedData()
        
        var remoteAddresses: [SocketAddress] = []
        if event.natIp > 0 && event.natPort > 0 {
            let address = SDLUtil.int32ToIp(event.natIp)
            if let remoteAddress = try? SocketAddress(ipAddress: address, port: Int(event.natPort)) {
                remoteAddresses.append(remoteAddress)
            }
        }
        
        if event.hasV6Info, let remoteAddress = try? await event.v6Info.socketAddress() {
            remoteAddresses.append(remoteAddress)
        }
        
        return .init(
            logMessage: "[SDLContext] sendRegisterEvent, ip: \(event)",
            action: .sendRegister(data: registerData, remoteAddresses: remoteAddresses)
        )
    }
}
