import Foundation

// MARK: - SyncStatus

enum SyncStatus: Int {
    case notNeeded = 0
    case batchStart = 1
    case batchEnd = 2
}

// MARK: - PacketSync (0x19)

/// Sync packet — batch message synchronization.
struct PacketSync: Packet {
    static let packetId = 0x19

    var status: SyncStatus = .notNeeded
    var timestamp: Int64 = 0
    var isMalformed: Bool = false
    var malformedFingerprint: String = ""

    func write(to stream: Stream) {
        stream.writeInt8(status.rawValue)
        stream.writeInt64(timestamp)
    }

    mutating func read(from stream: Stream) {
        do {
            let rawStatus = try stream.readInt8Strict()
            guard let parsedStatus = SyncStatus(rawValue: rawStatus) else {
                markMalformed("invalid_status:\(rawStatus)")
                return
            }

            let parsedTimestamp = try stream.readInt64Strict()

            guard !stream.hasRemainingBits() else {
                markMalformed("trailing_bits:\(stream.remainingBits())")
                return
            }

            status = parsedStatus
            timestamp = parsedTimestamp
            isMalformed = false
            malformedFingerprint = ""
        } catch {
            markMalformed(Self.errorFingerprint(error))
        }
    }

    private mutating func markMalformed(_ fingerprint: String) {
        status = .notNeeded
        timestamp = 0
        isMalformed = true
        malformedFingerprint = fingerprint
    }

    private static func errorFingerprint(_ error: Error) -> String {
        switch error {
        case PacketBitStreamError.underflow(let operation, let neededBits, let remainingBits):
            return "underflow:\(operation):\(neededBits):\(remainingBits)"
        case PacketBitStreamError.invalidStringLength(let length):
            return "invalid_string_length:\(length)"
        default:
            return "parse_error"
        }
    }
}
