package com.chick_mood.data.database

import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
import com.chick_mood.data.model.MoodRecord
import com.chick_mood.data.model.Emotion
import com.chick_mood.data.model.UserConfigEntry
import java.util.Date

/**
 * 简化的数据库测试
 *
 * 测试基本的数据库功能和数据完整性
 * 专注于验证Room数据库的核心功能
 *
 * @author Claude
 * @date 2025-10-22
 */
@RunWith(AndroidJUnit4::class)
class SimpleDatabaseTest {

    /**
     * 测试数据库实例
     */
    private lateinit var database: AppDatabase

    /**
     * 心情记录DAO
     */
    private lateinit var moodRecordDao: MoodRecordDao

    /**
     * 用户配置DAO
     */
    private lateinit var userConfigEntryDao: UserConfigEntryDao

    /**
     * 测试前准备
     */
    @Before
    fun createDb() {
        database = Room.inMemoryDatabaseBuilder(
            ApplicationProvider.getApplicationContext(),
            AppDatabase::class.java
        ).allowMainThreadQueries().build()

        moodRecordDao = database.moodRecordDao()
        userConfigEntryDao = database.userConfigEntryDao()
    }

    /**
     * 测试后清理
     */
    @After
    fun closeDb() {
        database.close()
    }

    // ==================== 心情记录基础测试 ====================

    /**
     * 测试插入和查询心情记录
     */
    @Test
    fun testInsertAndGetMoodRecord() = runBlocking {
        // 创建测试记录
        val testRecord = MoodRecord(
            emotion = Emotion.HAPPY,
            intensity = 85,
            noteText = "测试心情记录",
            imagePaths = emptyList(),
            timestamp = Date()
        )

        // 插入记录
        val insertedId = moodRecordDao.insertMoodRecord(testRecord)
        assertTrue("插入记录应该返回有效的ID", insertedId > 0)

        // 查询记录
        val retrievedRecord = moodRecordDao.getMoodRecordById(insertedId)
        assertNotNull("应该能查询到插入的记录", retrievedRecord)
        assertEquals("情绪类型应该正确", Emotion.HAPPY, retrievedRecord?.emotion)
        assertEquals("强度值应该正确", 85, retrievedRecord?.intensity)
        assertEquals("文字内容应该正确", "测试心情记录", retrievedRecord?.noteText)
    }

    /**
     * 测试获取所有心情记录
     */
    @Test
    fun testGetAllMoodRecords() = runBlocking {
        // 插入多条记录
        val testRecords = listOf(
            MoodRecord(emotion = Emotion.HAPPY, intensity = 85, noteText = "开心", imagePaths = emptyList(), timestamp = Date()),
            MoodRecord(emotion = Emotion.SAD, intensity = 60, noteText = "难过", imagePaths = emptyList(), timestamp = Date()),
            MoodRecord(emotion = Emotion.ANGRY, intensity = 90, noteText = "生气", imagePaths = emptyList(), timestamp = Date())
        )

        testRecords.forEach { record ->
            moodRecordDao.insertMoodRecord(record)
        }

        // 验证记录总数
        val totalCount = moodRecordDao.getMoodRecordCount()
        assertEquals("应该有3条记录", 3, totalCount)
    }

    /**
     * 测试删除心情记录
     */
    @Test
    fun testDeleteMoodRecord() = runBlocking {
        // 插入记录
        val testRecord = MoodRecord(emotion = Emotion.HAPPY, intensity = 85, noteText = "测试", imagePaths = emptyList(), timestamp = Date())
        val insertedId = moodRecordDao.insertMoodRecord(testRecord)
        assertEquals("插入后应该有1条记录", 1, moodRecordDao.getMoodRecordCount())

        // 删除记录
        val affectedRows = moodRecordDao.deleteMoodRecordById(insertedId)
        assertEquals("应该影响1行", 1, affectedRows)
        assertEquals("删除后应该没有记录", 0, moodRecordDao.getMoodRecordCount())
    }

    // ==================== 用户配置基础测试 ====================

    /**
     * 测试插入和查询用户配置
     */
    @Test
    fun testInsertAndGetUserConfig() = runBlocking {
        // 创建配置
        val testConfig = UserConfigEntry(
            configKey = "test_key",
            configValue = "test_value",
            updatedAt = System.currentTimeMillis()
        )

        // 插入配置
        val insertedId = userConfigEntryDao.insertOrUpdateUserConfig(testConfig)
        assertTrue("插入配置应该返回有效的ID", insertedId > 0)

        // 查询配置
        val retrievedConfig = userConfigEntryDao.getUserConfig("test_key")
        assertNotNull("应该能查询到配置", retrievedConfig)
        assertEquals("配置键应该正确", "test_key", retrievedConfig?.configKey)
        assertEquals("配置值应该正确", "test_value", retrievedConfig?.configValue)
    }

    /**
     * 测试用户昵称设置和获取
     */
    @Test
    fun testUserNickname() = runBlocking {
        // 设置昵称
        userConfigEntryDao.setUserNickname("测试用户")

        // 获取昵称
        val nickname = userConfigEntryDao.getUserNickname()
        assertEquals("昵称应该正确", "测试用户", nickname)
    }

    /**
     * 测试配置值设置和获取
     */
    @Test
    fun testConfigValue() = runBlocking {
        // 设置配置值
        userConfigEntryDao.setConfigValue("test_key", "test_value")

        // 获取配置值
        val value = userConfigEntryDao.getConfigValue("test_key")
        assertEquals("配置值应该正确", "test_value", value)
    }

    /**
     * 测试功能开关
     */
    @Test
    fun testFeatureEnabled() = runBlocking {
        // 启用功能
        userConfigEntryDao.setFeatureEnabled("test_feature", true)
        assertTrue("功能应该被启用", userConfigEntryDao.isFeatureEnabled("test_feature"))

        // 禁用功能
        userConfigEntryDao.setFeatureEnabled("test_feature", false)
        assertFalse("功能应该被禁用", userConfigEntryDao.isFeatureEnabled("test_feature"))
    }

    // ==================== 类型转换测试 ====================

    /**
     * 测试日期类型转换
     */
    @Test
    fun testDateConversion() {
        val converters = Converters()
        val testDate = Date()
        val testTimestamp = testDate.time

        // 测试日期转时间戳
        val timestamp = converters.toDate(testDate)
        assertEquals("日期应该转换为正确的时间戳", testTimestamp, timestamp)

        // 测试时间戳转日期
        val date = converters.fromDate(testTimestamp)
        assertEquals("时间戳应该转换为正确的日期", testTimestamp, date.time)
    }

    /**
     * 测试枚举类型转换
     */
    @Test
    fun testEmotionConversion() {
        val converters = Converters()

        // 测试枚举转字符串
        val emotionString = converters.fromEmotion(Emotion.HAPPY)
        assertEquals("枚举应该转换为字符串名称", "HAPPY", emotionString)

        // 测试字符串转枚举
        val emotion = converters.toEmotion("HAPPY")
        assertEquals("字符串应该转换为对应枚举", Emotion.HAPPY, emotion)

        // 测试无效枚举值
        val defaultEmotion = converters.toEmotion("INVALID_EMOTION")
        assertEquals("无效枚举应该返回默认值", Emotion.HAPPY, defaultEmotion)
    }

    /**
     * 测试布尔类型转换
     */
    @Test
    fun testBooleanConversion() {
        val converters = Converters()

        // 测试布尔值转整数
        assertEquals("true应该转换为1", 1, converters.fromBoolean(true))
        assertEquals("false应该转换为0", 0, converters.fromBoolean(false))

        // 测试整数转布尔值
        assertTrue("1应该转换为true", converters.toBoolean(1))
        assertFalse("0应该转换为false", converters.toBoolean(0))
        assertFalse("其他数字应该转换为false", converters.toBoolean(2))
    }

    // ==================== 数据完整性测试 ====================

    /**
     * 测试数据库版本
     */
    @Test
    fun testDatabaseVersion() {
        assertEquals("数据库版本应该是2", 2, AppDatabase.DATABASE_VERSION)
        assertEquals("数据库名称应该正确", "chick_mood_database", AppDatabase.DATABASE_NAME)
    }

    /**
     * 测试空数据库状态
     */
    @Test
    fun testEmptyDatabaseState() = runBlocking {
        // 初始状态应该没有记录
        assertEquals("初始应该没有心情记录", 0, moodRecordDao.getMoodRecordCount())

        // 查询不存在的记录应该返回null
        assertNull("查询不存在的记录应该返回null", moodRecordDao.getMoodRecordById(999L))

        // 查询不存在的配置应该返回null
        assertNull("查询不存在的配置应该返回null", userConfigEntryDao.getUserConfig("nonexistent_key"))
    }

    /**
     * 测试批量操作
     */
    @Test
    fun testBatchOperations() = runBlocking {
        // 批量插入配置
        val configs = listOf(
            UserConfigEntry(configKey = "key1", configValue = "value1", updatedAt = System.currentTimeMillis()),
            UserConfigEntry(configKey = "key2", configValue = "value2", updatedAt = System.currentTimeMillis()),
            UserConfigEntry(configKey = "key3", configValue = "value3", updatedAt = System.currentTimeMillis())
        )

        val insertedIds = userConfigEntryDao.insertConfigs(configs)
        assertEquals("应该插入3个配置", 3, insertedIds.size)
        assertTrue("所有插入ID都应该有效", insertedIds.all { it > 0 })

        // 验证所有配置都能查询到
        for (config in configs) {
            val retrieved = userConfigEntryDao.getUserConfig(config.configKey)
            assertNotNull("应该能查询到配置: ${config.configKey}", retrieved)
            assertEquals("配置值应该正确", config.configValue, retrieved?.configValue)
        }
    }
}