package com.yorvana.ui.settings

import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import androidx.navigation3.runtime.NavBackStack
import androidx.navigation3.runtime.NavKey
import com.yorvana.TestYorvanaApplication
import com.yorvana.data.model.OdometerUnit
import com.yorvana.ui.TestTags
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.flow.MutableStateFlow
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config

@Config(application = TestYorvanaApplication::class, sdk = [34])
@RunWith(RobolectricTestRunner::class)
class SettingsScreenIT {
    @get:Rule
    val composeTestRule = createComposeRule()

    @Test
    fun settingsScreen_displaysCorrectInformation() {
        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
        val stateFlow =
            MutableStateFlow(
                SettingsState(
                    vaultUriString = "content://test-vault",
                    defaultOdometerUnit = OdometerUnit.KM,
                    defaultCurrency = "EUR",
                    appVersion = "1.0.0",
                ),
            )
        every { mockViewModel.state } returns stateFlow

        val mockBackStack = mockk<NavBackStack<NavKey>>(relaxed = true)

        composeTestRule.setContent {
            SettingsScreen(
                backStack = mockBackStack,
                viewModel = mockViewModel,
            )
        }

        // Verify Title
        composeTestRule.onNodeWithTag("ScreenTitle").assertIsDisplayed()

        // Verify Preferences section
        composeTestRule.onNodeWithText("odometer unit", substring = true, ignoreCase = true).performScrollTo().assertIsDisplayed()
        composeTestRule.onNodeWithText("km", substring = true, ignoreCase = true).performScrollTo().assertIsDisplayed()

        composeTestRule.onNodeWithText("Currency", substring = true, ignoreCase = true).performScrollTo().assertIsDisplayed()
        composeTestRule.onNodeWithText("EUR", substring = true, ignoreCase = true).performScrollTo().assertIsDisplayed()

        // Verify Application section
        composeTestRule.onNodeWithText("Version", substring = true, ignoreCase = true).performScrollTo().assertIsDisplayed()
        composeTestRule.onNodeWithText("1.0.0", substring = true, ignoreCase = true).performScrollTo().assertIsDisplayed()
    }

    @Test
    fun clickCategories_triggersOpenCategoriesEvent() {
        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
        val stateFlow =
            MutableStateFlow(
                SettingsState(
                    vaultUriString = "content://test-vault",
                    defaultOdometerUnit = OdometerUnit.KM,
                    defaultCurrency = "USD",
                    appVersion = "1.0.0",
                ),
            )
        every { mockViewModel.state } returns stateFlow

        val mockBackStack = mockk<NavBackStack<NavKey>>(relaxed = true)

        composeTestRule.setContent {
            SettingsScreen(
                backStack = mockBackStack,
                viewModel = mockViewModel,
            )
        }

        // Click on Categories
        composeTestRule.onNodeWithText("categories", substring = true, ignoreCase = true).performScrollTo().performClick()

        // Verify ViewModel receives OpenCategories event
        verify { mockViewModel.onEvent(SettingsEvent.OpenCategories) }
    }

    @Test
    fun clickContact_triggersOpenContactEvent() {
        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
        val stateFlow =
            MutableStateFlow(
                SettingsState(
                    vaultUriString = "content://test-vault",
                    defaultOdometerUnit = OdometerUnit.KM,
                    defaultCurrency = "USD",
                    appVersion = "1.0.0",
                ),
            )
        every { mockViewModel.state } returns stateFlow

        val mockBackStack = mockk<NavBackStack<NavKey>>(relaxed = true)

        composeTestRule.setContent {
            SettingsScreen(
                backStack = mockBackStack,
                viewModel = mockViewModel,
            )
        }

        composeTestRule.onNodeWithTag(TestTags.SETTINGS_CONTACT_ROW).performScrollTo().performClick()

        verify { mockViewModel.onEvent(SettingsEvent.OpenContact) }
    }

    @Test
    fun settingsScreen_showsConflictDialog_whenStateIsTrue() {
        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
        val stateFlow =
            MutableStateFlow(
                SettingsState(
                    vaultUriString = "content://test-vault",
                    showConflictDialog = true,
                ),
            )
        every { mockViewModel.state } returns stateFlow

        val mockBackStack = mockk<NavBackStack<NavKey>>(relaxed = true)

        composeTestRule.setContent {
            SettingsScreen(
                backStack = mockBackStack,
                viewModel = mockViewModel,
            )
        }

        // Verify Conflict Dialog is displayed
        composeTestRule.onNodeWithText("Folder Not Empty", substring = true, ignoreCase = true).assertIsDisplayed()
        composeTestRule.onNodeWithText("is not a Yorvana vault", substring = true, ignoreCase = true).assertIsDisplayed()

        // Click OK
        composeTestRule.onNodeWithText("OK").performClick()

        // Verify Dismiss event
        verify { mockViewModel.onEvent(SettingsEvent.DismissConflictDialog) }
    }

    @Test
    fun settingsScreen_showsValidatingDialog_whenStateIsTrue() {
        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
        val stateFlow =
            MutableStateFlow(
                SettingsState(isValidating = true),
            )
        every { mockViewModel.state } returns stateFlow

        composeTestRule.setContent {
            SettingsScreen(
                backStack = mockk(relaxed = true),
                viewModel = mockViewModel,
            )
        }

        composeTestRule.onNodeWithText("Validating folder", substring = true, ignoreCase = true).assertIsDisplayed()
    }

    @Test
    fun settingsScreen_showsExistingVaultDialog_whenStateIsTrue() {
        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
        val stateFlow =
            MutableStateFlow(
                SettingsState(showUseExistingVaultDialog = true),
            )
        every { mockViewModel.state } returns stateFlow

        composeTestRule.setContent {
            SettingsScreen(
                backStack = mockk(relaxed = true),
                viewModel = mockViewModel,
            )
        }

        composeTestRule.onNodeWithText("Existing Vault Found", substring = true, ignoreCase = true).assertIsDisplayed()
        composeTestRule.onNodeWithText("Use this vault").performClick()

        verify { mockViewModel.onEvent(SettingsEvent.StartFresh) }
    }
}
