import Foundation
import GRDB

/// SQLite record for the `dialogs` table.
/// Android parity: `DialogEntity` in `MessageEntities.kt`.
struct DialogRecord: Codable, FetchableRecord, MutablePersistableRecord, Sendable {
    static let databaseTableName = "dialogs"

    var id: Int64?
    var account: String
    var opponentKey: String
    var opponentTitle: String
    var opponentUsername: String
    var lastMessage: String
    var lastMessageTimestamp: Int64
    var unreadCount: Int
    var isOnline: Int
    var lastSeen: Int64
    var verified: Int
    var iHaveSent: Int
    var isPinned: Int
    var isMuted: Int
    var lastMessageFromMe: Int
    var lastMessageDelivered: Int
    var lastMessageRead: Int
    var lastMessageSenderKey: String

    // MARK: - Column mapping

    enum Columns: String, ColumnExpression {
        case id, account
        case opponentKey = "opponent_key"
        case opponentTitle = "opponent_title"
        case opponentUsername = "opponent_username"
        case lastMessage = "last_message"
        case lastMessageTimestamp = "last_message_timestamp"
        case unreadCount = "unread_count"
        case isOnline = "is_online"
        case lastSeen = "last_seen"
        case verified
        case iHaveSent = "i_have_sent"
        case isPinned = "is_pinned"
        case isMuted = "is_muted"
        case lastMessageFromMe = "last_message_from_me"
        case lastMessageDelivered = "last_message_delivered"
        case lastMessageRead = "last_message_read"
        case lastMessageSenderKey = "last_message_sender_key"
    }

    enum CodingKeys: String, CodingKey {
        case id, account
        case opponentKey = "opponent_key"
        case opponentTitle = "opponent_title"
        case opponentUsername = "opponent_username"
        case lastMessage = "last_message"
        case lastMessageTimestamp = "last_message_timestamp"
        case unreadCount = "unread_count"
        case isOnline = "is_online"
        case lastSeen = "last_seen"
        case verified
        case iHaveSent = "i_have_sent"
        case isPinned = "is_pinned"
        case isMuted = "is_muted"
        case lastMessageFromMe = "last_message_from_me"
        case lastMessageDelivered = "last_message_delivered"
        case lastMessageRead = "last_message_read"
        case lastMessageSenderKey = "last_message_sender_key"
    }

    // MARK: - Auto-increment

    mutating func didInsert(_ inserted: InsertionSuccess) {
        id = inserted.rowID
    }

    // MARK: - Conversions

    func toDialog() -> Dialog {
        var d = Dialog(
            id: opponentKey,
            account: account,
            opponentKey: opponentKey,
            opponentTitle: opponentTitle,
            opponentUsername: opponentUsername,
            lastMessage: lastMessage,
            lastMessageTimestamp: lastMessageTimestamp,
            unreadCount: unreadCount,
            isOnline: isOnline != 0,
            lastSeen: lastSeen,
            verified: verified,
            iHaveSent: iHaveSent != 0,
            isPinned: isPinned != 0,
            isMuted: isMuted != 0,
            lastMessageFromMe: lastMessageFromMe != 0,
            lastMessageDelivered: DeliveryStatus(rawValue: lastMessageDelivered) ?? .waiting,
            lastMessageRead: lastMessageRead != 0
        )
        d.lastMessageSenderKey = lastMessageSenderKey
        return d
    }

    static func from(_ dialog: Dialog) -> DialogRecord {
        DialogRecord(
            id: nil,
            account: dialog.account,
            opponentKey: dialog.opponentKey,
            opponentTitle: dialog.opponentTitle,
            opponentUsername: dialog.opponentUsername,
            lastMessage: dialog.lastMessage,
            lastMessageTimestamp: dialog.lastMessageTimestamp,
            unreadCount: dialog.unreadCount,
            isOnline: dialog.isOnline ? 1 : 0,
            lastSeen: dialog.lastSeen,
            verified: dialog.verified,
            iHaveSent: dialog.iHaveSent ? 1 : 0,
            isPinned: dialog.isPinned ? 1 : 0,
            isMuted: dialog.isMuted ? 1 : 0,
            lastMessageFromMe: dialog.lastMessageFromMe ? 1 : 0,
            lastMessageDelivered: dialog.lastMessageDelivered.rawValue,
            lastMessageRead: dialog.lastMessageRead ? 1 : 0,
            lastMessageSenderKey: dialog.lastMessageSenderKey
        )
    }
}
