import Foundation
import SwiftData

@Model
final class HistoryItem {
    
    let startDate: Date
    
    let message: HistoryMessage
    
    let route: TransmissionType
    
    let finishDate: Date
    
    init(message: Message, startDate: Date, route: TransmissionType, finishDate: Date) {
        self.startDate = startDate
        self.message = .init(
            messageType: message.messageType,
            clientChallenge: Int(message.clientChallenge),
            serverChallenge: Int(message.serverChallenge),
            result: message.result)
        self.finishDate = finishDate
        self.route = route
    }
    
    var roundTripTime: TimeInterval {
        finishDate.timeIntervalSince(startDate)
    }
    
    var response: MessageResult {
        message.result
    }
}

struct HistoryMessage {
        
        /// The type of message being sent.
        let messageType: MessageType
        
        /**
         * The random nonce created by the remote
         *
         * This nonce is a random number created by the remote, different for each unlock request.
         * It is set for all message types.
         */
        let clientChallenge: Int
        
        /**
         * A random number to sign by the remote
         *
         * This nonce is set by the server after receiving an initial message.
         * It is set for the message types `challenge`, `request`, and `response`.
         */
        let serverChallenge: Int
        
        /**
         * The response status for the previous message.
         *
         * It is set only for messages from the server, e.g. the `challenge` and `response` message types.
         * Must be set to `MessageAccepted` for other messages.
         */
        let result: MessageResult
    }

extension HistoryMessage: Encodable {
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        try container.encode(messageType)
        try container.encode(clientChallenge)
        try container.encode(serverChallenge)
        try container.encode(result)
    }
}

extension HistoryMessage: Decodable {
    
    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        self.messageType = try container.decode(MessageType.self)
        self.clientChallenge = try container.decode(Int.self)
        self.serverChallenge = try container.decode(Int.self)
        self.result = try container.decode(MessageResult.self)
    }
}


extension HistoryItem: Identifiable {
    
    var id: Double {
        startDate.timeIntervalSince1970
    }
}

extension HistoryItem: Comparable {
    
    static func < (lhs: HistoryItem, rhs: HistoryItem) -> Bool {
        lhs.startDate < rhs.startDate
    }
}

extension HistoryItem {
    
    static var mock: HistoryItem {
        let message = Message(messageType: .request, clientChallenge: 123, serverChallenge: 234, result: .unlocked)
        return .init(
            message: message,
            startDate: Date.now.addingTimeInterval(-5),
            route: .throughServer,
            finishDate: Date.now)
    }
}
