package com.durian.tssparty.data.local

import androidx.room.*
import kotlinx.coroutines.flow.Flow

/**
 * Entity for storing TSS share records
 */
@Entity(tableName = "share_records")
data class ShareRecordEntity(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,

    @ColumnInfo(name = "session_id")
    val sessionId: String,

    @ColumnInfo(name = "public_key")
    val publicKey: String,

    @ColumnInfo(name = "encrypted_share")
    val encryptedShare: String,

    @ColumnInfo(name = "threshold_t")
    val thresholdT: Int,

    @ColumnInfo(name = "threshold_n")
    val thresholdN: Int,

    @ColumnInfo(name = "party_index")
    val partyIndex: Int,

    @ColumnInfo(name = "party_id")
    val partyId: String,  // The original partyId used during keygen - required for signing

    @ColumnInfo(name = "address")
    val address: String,

    @ColumnInfo(name = "created_at")
    val createdAt: Long = System.currentTimeMillis()
)

/**
 * DAO for share records
 */
@Dao
interface ShareRecordDao {
    @Query("SELECT * FROM share_records ORDER BY created_at DESC")
    fun getAllShares(): Flow<List<ShareRecordEntity>>

    @Query("SELECT * FROM share_records WHERE id = :id")
    suspend fun getShareById(id: Long): ShareRecordEntity?

    @Query("SELECT * FROM share_records WHERE session_id = :sessionId")
    suspend fun getShareBySessionId(sessionId: String): ShareRecordEntity?

    @Query("SELECT * FROM share_records WHERE address = :address")
    suspend fun getShareByAddress(address: String): ShareRecordEntity?

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertShare(share: ShareRecordEntity): Long

    @Delete
    suspend fun deleteShare(share: ShareRecordEntity)

    @Query("DELETE FROM share_records WHERE id = :id")
    suspend fun deleteShareById(id: Long)

    @Query("SELECT COUNT(*) FROM share_records")
    suspend fun getShareCount(): Int
}

/**
 * Entity for storing app settings (like persistent partyId)
 */
@Entity(tableName = "app_settings")
data class AppSettingEntity(
    @PrimaryKey
    val key: String,

    @ColumnInfo(name = "value")
    val value: String
)

/**
 * DAO for app settings
 */
@Dao
interface AppSettingDao {
    @Query("SELECT value FROM app_settings WHERE `key` = :key")
    suspend fun getValue(key: String): String?

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun setValue(setting: AppSettingEntity)
}

/**
 * 转账记录数据库实体
 * Entity for storing transaction history records
 */
@Entity(
    tableName = "transaction_records",
    foreignKeys = [
        ForeignKey(
            entity = ShareRecordEntity::class,
            parentColumns = ["id"],
            childColumns = ["share_id"],
            onDelete = ForeignKey.CASCADE  // 删除钱包时自动删除关联的转账记录
        )
    ],
    indices = [
        Index(value = ["share_id"]),
        Index(value = ["tx_hash"], unique = true),
        Index(value = ["from_address"]),
        Index(value = ["to_address"]),
        Index(value = ["created_at"])
    ]
)
data class TransactionRecordEntity(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,

    @ColumnInfo(name = "share_id")
    val shareId: Long,               // 关联的钱包ID

    @ColumnInfo(name = "from_address")
    val fromAddress: String,         // 发送方地址

    @ColumnInfo(name = "to_address")
    val toAddress: String,           // 接收方地址

    @ColumnInfo(name = "amount")
    val amount: String,              // 转账金额（人类可读格式）

    @ColumnInfo(name = "token_type")
    val tokenType: String,           // 代币类型：KAVA, GREEN_POINTS, ENERGY_POINTS, FUTURE_POINTS

    @ColumnInfo(name = "tx_hash")
    val txHash: String,              // 交易哈希

    @ColumnInfo(name = "gas_price")
    val gasPrice: String,            // Gas 价格（Wei）

    @ColumnInfo(name = "gas_used")
    val gasUsed: String = "",        // 实际消耗的 Gas

    @ColumnInfo(name = "tx_fee")
    val txFee: String = "",          // 交易手续费

    @ColumnInfo(name = "status")
    val status: String,              // 交易状态：PENDING, CONFIRMED, FAILED

    @ColumnInfo(name = "direction")
    val direction: String,           // 交易方向：SENT, RECEIVED

    @ColumnInfo(name = "note")
    val note: String = "",           // 备注

    @ColumnInfo(name = "created_at")
    val createdAt: Long = System.currentTimeMillis(),

    @ColumnInfo(name = "confirmed_at")
    val confirmedAt: Long? = null,   // 确认时间

    @ColumnInfo(name = "block_number")
    val blockNumber: Long? = null    // 区块高度
)

/**
 * 转账记录 DAO
 * Data Access Object for transaction records
 */
@Dao
interface TransactionRecordDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertRecord(record: TransactionRecordEntity): Long

    @Query("SELECT * FROM transaction_records WHERE id = :id")
    suspend fun getRecordById(id: Long): TransactionRecordEntity?

    @Query("SELECT * FROM transaction_records WHERE tx_hash = :txHash")
    suspend fun getRecordByTxHash(txHash: String): TransactionRecordEntity?

    @Query("SELECT * FROM transaction_records WHERE share_id = :shareId ORDER BY created_at DESC")
    fun getRecordsForShare(shareId: Long): Flow<List<TransactionRecordEntity>>

    @Query("SELECT * FROM transaction_records WHERE share_id = :shareId ORDER BY created_at DESC LIMIT :limit OFFSET :offset")
    suspend fun getRecordsForSharePaged(shareId: Long, limit: Int, offset: Int): List<TransactionRecordEntity>

    @Query("SELECT * FROM transaction_records WHERE share_id = :shareId AND token_type = :tokenType ORDER BY created_at DESC")
    fun getRecordsForShareByToken(shareId: Long, tokenType: String): Flow<List<TransactionRecordEntity>>

    @Query("SELECT * FROM transaction_records WHERE status = 'PENDING' ORDER BY created_at ASC")
    suspend fun getPendingRecords(): List<TransactionRecordEntity>

    @Query("UPDATE transaction_records SET status = :status, confirmed_at = :confirmedAt, block_number = :blockNumber, gas_used = :gasUsed, tx_fee = :txFee WHERE id = :id")
    suspend fun updateStatus(id: Long, status: String, confirmedAt: Long?, blockNumber: Long?, gasUsed: String, txFee: String)

    @Query("""
        SELECT
            COUNT(*) as total_count,
            SUM(CASE WHEN direction = 'SENT' THEN 1 ELSE 0 END) as sent_count,
            SUM(CASE WHEN direction = 'RECEIVED' THEN 1 ELSE 0 END) as received_count
        FROM transaction_records
        WHERE share_id = :shareId AND token_type = :tokenType
    """)
    suspend fun getTransactionStats(shareId: Long, tokenType: String): TransactionStats

    @Query("SELECT COALESCE(SUM(CAST(amount AS REAL)), 0) FROM transaction_records WHERE share_id = :shareId AND token_type = :tokenType AND direction = 'SENT' AND status = 'CONFIRMED'")
    suspend fun getTotalSentAmount(shareId: Long, tokenType: String): Double

    @Query("SELECT COALESCE(SUM(CAST(amount AS REAL)), 0) FROM transaction_records WHERE share_id = :shareId AND token_type = :tokenType AND direction = 'RECEIVED' AND status = 'CONFIRMED'")
    suspend fun getTotalReceivedAmount(shareId: Long, tokenType: String): Double

    @Query("SELECT COALESCE(SUM(CAST(tx_fee AS REAL)), 0) FROM transaction_records WHERE share_id = :shareId AND direction = 'SENT' AND status = 'CONFIRMED'")
    suspend fun getTotalTxFee(shareId: Long): Double

    @Query("DELETE FROM transaction_records WHERE id = :id")
    suspend fun deleteRecordById(id: Long)

    @Query("DELETE FROM transaction_records WHERE share_id = :shareId")
    suspend fun deleteRecordsForShare(shareId: Long)

    @Query("SELECT COUNT(*) FROM transaction_records WHERE share_id = :shareId")
    suspend fun getRecordCount(shareId: Long): Int
}

/**
 * 转账统计数据类
 */
data class TransactionStats(
    @ColumnInfo(name = "total_count")
    val totalCount: Int,
    @ColumnInfo(name = "sent_count")
    val sentCount: Int,
    @ColumnInfo(name = "received_count")
    val receivedCount: Int
)

/**
 * Room database
 */
@Database(
    entities = [ShareRecordEntity::class, AppSettingEntity::class, TransactionRecordEntity::class],
    version = 4,  // Version 4: added transaction_records table for transfer history
    exportSchema = false
)
abstract class TssDatabase : RoomDatabase() {
    abstract fun shareRecordDao(): ShareRecordDao
    abstract fun appSettingDao(): AppSettingDao
    abstract fun transactionRecordDao(): TransactionRecordDao
}
