package com.durian.tssparty.domain.model

import com.google.gson.annotations.SerializedName

/**
 * Participant in a TSS session
 */
data class Participant(
    @SerializedName("partyId")
    val partyId: String,
    @SerializedName("partyIndex")
    val partyIndex: Int,
    @SerializedName("name")
    val name: String = ""
)

/**
 * TSS Session information
 */
data class TssSession(
    val sessionId: String,
    val sessionType: SessionType,
    val thresholdT: Int,
    val thresholdN: Int,
    val participants: List<Participant>,
    val status: SessionStatus,
    val inviteCode: String? = null,
    val messageHash: String? = null,
    val createdAt: Long = System.currentTimeMillis()
)

enum class SessionType {
    KEYGEN,
    SIGN
}

enum class SessionStatus {
    WAITING,
    IN_PROGRESS,
    COMPLETED,
    FAILED
}

/**
 * Result of key generation
 */
data class KeygenResult(
    @SerializedName("publicKey")
    val publicKey: String,  // base64 encoded
    @SerializedName("encryptedShare")
    val encryptedShare: String  // base64 encoded
)

/**
 * Result of signing
 */
data class SignResult(
    @SerializedName("signature")
    val signature: String,  // base64 encoded (r || s || v, 65 bytes)
    @SerializedName("recoveryId")
    val recoveryId: Int
)

/**
 * Outgoing TSS message
 */
data class TssOutgoingMessage(
    @SerializedName("type")
    val type: String,
    @SerializedName("isBroadcast")
    val isBroadcast: Boolean,
    @SerializedName("toParties")
    val toParties: List<String>?,
    @SerializedName("payload")
    val payload: String  // base64 encoded
)

/**
 * Share record stored in local database
 */
data class ShareRecord(
    val id: Long = 0,
    val sessionId: String,
    val publicKey: String,
    val encryptedShare: String,
    val thresholdT: Int,
    val thresholdN: Int,
    val partyIndex: Int,
    val partyId: String,  // The original partyId used during keygen - required for signing
    val address: String,
    val createdAt: Long = System.currentTimeMillis()
)

/**
 * Account balance information
 */
data class AccountBalance(
    val address: String,
    val balance: String,
    val denom: String = "ukava"
)

/**
 * Sign session request
 */
data class SignSessionRequest(
    val sessionId: String,
    val messageHash: String,  // hex encoded
    val participants: List<Participant>
)

/**
 * Settings
 * Matches service-party-app settings structure
 */
data class AppSettings(
    val messageRouterUrl: String = "mpc-grpc.szaiai.com:443",
    val accountServiceUrl: String = "https://rwaapi.szaiai.com",
    val kavaRpcUrl: String = "https://evm.kava.io",
    val networkType: NetworkType = NetworkType.MAINNET
)

enum class NetworkType {
    MAINNET,
    TESTNET
}

/**
 * Token type for transfers
 */
enum class TokenType {
    KAVA,           // Native KAVA token
    GREEN_POINTS,   // 绿积分 (dUSDT) ERC-20 token
    ENERGY_POINTS,  // 积分股 (eUSDT) ERC-20 token
    FUTURE_POINTS   // 积分值 (fUSDT) ERC-20 token
}

/**
 * ERC-20 通用函数签名（keccak256 哈希的前4字节）
 * Common ERC-20 function selectors
 */
object ERC20Selectors {
    const val BALANCE_OF = "0x70a08231"    // balanceOf(address)
    const val TRANSFER = "0xa9059cbb"      // transfer(address,uint256)
    const val APPROVE = "0x095ea7b3"       // approve(address,uint256)
    const val ALLOWANCE = "0xdd62ed3e"     // allowance(address,address)
    const val TOTAL_SUPPLY = "0x18160ddd"  // totalSupply()
}

/**
 * Green Points (绿积分) Token Contract Configuration
 * dUSDT - Fixed supply ERC-20 token on Kava EVM
 */
object GreenPointsToken {
    const val CONTRACT_ADDRESS = "0xA9F3A35dBa8699c8C681D8db03F0c1A8CEB9D7c3"
    const val NAME = "绿积分"
    const val SYMBOL = "dUSDT"
    const val DECIMALS = 6

    // ERC-20 function signatures (kept for backward compatibility)
    const val BALANCE_OF_SELECTOR = ERC20Selectors.BALANCE_OF
    const val TRANSFER_SELECTOR = ERC20Selectors.TRANSFER
    const val APPROVE_SELECTOR = ERC20Selectors.APPROVE
    const val ALLOWANCE_SELECTOR = ERC20Selectors.ALLOWANCE
    const val TOTAL_SUPPLY_SELECTOR = ERC20Selectors.TOTAL_SUPPLY
}

/**
 * Energy Points (积分股) Token Contract Configuration
 * eUSDT - ERC-20 token on Kava EVM
 * 总供应量：100.02亿 (10,002,000,000)
 */
object EnergyPointsToken {
    const val CONTRACT_ADDRESS = "0x7C3275D808eFbAE90C06C7E3A9AfDdcAa8563931"
    const val NAME = "积分股"
    const val SYMBOL = "eUSDT"
    const val DECIMALS = 6  // 与 dUSDT 相同的精度
}

/**
 * Future Points (积分值) Token Contract Configuration
 * fUSDT - ERC-20 token on Kava EVM
 * 总供应量：1万亿 (1,000,000,000,000)
 */
object FuturePointsToken {
    const val CONTRACT_ADDRESS = "0x14dc4f7d3E4197438d058C3D156dd9826A161134"
    const val NAME = "积分值"
    const val SYMBOL = "fUSDT"
    const val DECIMALS = 6  // 与 dUSDT 相同的精度
}

/**
 * 代币配置工具类
 * Token configuration utility
 */
object TokenConfig {
    /**
     * 获取代币合约地址
     */
    fun getContractAddress(tokenType: TokenType): String? {
        return when (tokenType) {
            TokenType.KAVA -> null  // 原生代币无合约地址
            TokenType.GREEN_POINTS -> GreenPointsToken.CONTRACT_ADDRESS
            TokenType.ENERGY_POINTS -> EnergyPointsToken.CONTRACT_ADDRESS
            TokenType.FUTURE_POINTS -> FuturePointsToken.CONTRACT_ADDRESS
        }
    }

    /**
     * 获取代币精度
     */
    fun getDecimals(tokenType: TokenType): Int {
        return when (tokenType) {
            TokenType.KAVA -> 18  // KAVA 原生代币精度
            TokenType.GREEN_POINTS -> GreenPointsToken.DECIMALS
            TokenType.ENERGY_POINTS -> EnergyPointsToken.DECIMALS
            TokenType.FUTURE_POINTS -> FuturePointsToken.DECIMALS
        }
    }

    /**
     * 获取代币名称
     */
    fun getName(tokenType: TokenType): String {
        return when (tokenType) {
            TokenType.KAVA -> "KAVA"
            TokenType.GREEN_POINTS -> GreenPointsToken.NAME
            TokenType.ENERGY_POINTS -> EnergyPointsToken.NAME
            TokenType.FUTURE_POINTS -> FuturePointsToken.NAME
        }
    }

    /**
     * 获取代币符号
     */
    fun getSymbol(tokenType: TokenType): String {
        return when (tokenType) {
            TokenType.KAVA -> "KAVA"
            TokenType.GREEN_POINTS -> GreenPointsToken.SYMBOL
            TokenType.ENERGY_POINTS -> EnergyPointsToken.SYMBOL
            TokenType.FUTURE_POINTS -> FuturePointsToken.SYMBOL
        }
    }

    /**
     * 判断是否为 ERC-20 代币
     */
    fun isERC20(tokenType: TokenType): Boolean {
        return tokenType != TokenType.KAVA
    }
}

/**
 * Wallet balance containing native and all token balances
 * 钱包余额，包含原生代币和所有 ERC-20 代币余额
 */
data class WalletBalance(
    val address: String,
    val kavaBalance: String = "0",           // Native KAVA balance
    val greenPointsBalance: String = "0",    // 绿积分 (dUSDT) balance
    val energyPointsBalance: String = "0",   // 积分股 (eUSDT) balance
    val futurePointsBalance: String = "0"    // 积分值 (fUSDT) balance
) {
    /**
     * 根据代币类型获取余额
     */
    fun getBalance(tokenType: TokenType): String {
        return when (tokenType) {
            TokenType.KAVA -> kavaBalance
            TokenType.GREEN_POINTS -> greenPointsBalance
            TokenType.ENERGY_POINTS -> energyPointsBalance
            TokenType.FUTURE_POINTS -> futurePointsBalance
        }
    }
}

/**
 * Share backup data for export/import
 * Contains all necessary information to restore a wallet share
 */
data class ShareBackup(
    @SerializedName("version")
    val version: Int = 2,  // Version 2: added partyId field for proper backup/restore

    @SerializedName("sessionId")
    val sessionId: String,

    @SerializedName("publicKey")
    val publicKey: String,  // base64 encoded

    @SerializedName("encryptedShare")
    val encryptedShare: String,  // base64 encoded, encrypted with user password

    @SerializedName("thresholdT")
    val thresholdT: Int,

    @SerializedName("thresholdN")
    val thresholdN: Int,

    @SerializedName("partyIndex")
    val partyIndex: Int,

    @SerializedName("partyId")
    val partyId: String,  // The original partyId used during keygen - CRITICAL for signing after restore

    @SerializedName("address")
    val address: String,

    @SerializedName("createdAt")
    val createdAt: Long,

    @SerializedName("exportedAt")
    val exportedAt: Long = System.currentTimeMillis()
) {
    companion object {
        const val FILE_EXTENSION = "tss-backup"
        const val MIME_TYPE = "application/octet-stream"

        /**
         * Create backup from ShareRecord
         */
        fun fromShareRecord(share: ShareRecord): ShareBackup {
            return ShareBackup(
                sessionId = share.sessionId,
                publicKey = share.publicKey,
                encryptedShare = share.encryptedShare,
                thresholdT = share.thresholdT,
                thresholdN = share.thresholdN,
                partyIndex = share.partyIndex,
                partyId = share.partyId,
                address = share.address,
                createdAt = share.createdAt
            )
        }
    }

    /**
     * Convert backup to ShareRecord for database storage
     */
    fun toShareRecord(): ShareRecord {
        return ShareRecord(
            id = 0,  // Will be auto-generated
            sessionId = sessionId,
            publicKey = publicKey,
            encryptedShare = encryptedShare,
            thresholdT = thresholdT,
            thresholdN = thresholdN,
            partyIndex = partyIndex,
            partyId = partyId,
            address = address,
            createdAt = createdAt
        )
    }
}
