import Foundation

// MARK: - LayoutEngine

/// Background layout calculation via Swift Actor.
/// Replaces synchronous main-thread layout with async computation.
/// Actor serializes requests — race conditions impossible.
actor LayoutEngine {

    static let shared = LayoutEngine()

    private var generation: UInt64 = 0

    // MARK: - Request / Result

    struct LayoutRequest: Sendable {
        let messages: [ChatMessage]
        let maxBubbleWidth: CGFloat
        let currentPublicKey: String
        let opponentPublicKey: String
        let opponentTitle: String
        let isGroupChat: Bool
        let groupAdminKey: String
        let isDarkMode: Bool
        let dirtyIds: Set<String>?
        let existingLayouts: [String: MessageCellLayout]?
        let existingTextLayouts: [String: CoreTextTextLayout]?
    }

    struct LayoutResult: Sendable {
        let layouts: [String: MessageCellLayout]
        let textLayouts: [String: CoreTextTextLayout]
        let generation: UInt64
    }

    // MARK: - Calculate

    func calculate(_ request: LayoutRequest) -> LayoutResult {
        generation += 1
        let gen = generation

        let (layouts, textLayouts) = MessageCellLayout.batchCalculate(
            messages: request.messages,
            maxBubbleWidth: request.maxBubbleWidth,
            currentPublicKey: request.currentPublicKey,
            opponentPublicKey: request.opponentPublicKey,
            opponentTitle: request.opponentTitle,
            isGroupChat: request.isGroupChat,
            groupAdminKey: request.groupAdminKey,
            isDarkMode: request.isDarkMode,
            dirtyIds: request.dirtyIds,
            existingLayouts: request.existingLayouts,
            existingTextLayouts: request.existingTextLayouts
        )

        return LayoutResult(layouts: layouts, textLayouts: textLayouts, generation: gen)
    }
}
