package com.durian.tssparty

import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.durian.tssparty.domain.model.AppReadyState
import com.durian.tssparty.domain.model.ShareBackup
import com.durian.tssparty.domain.model.TokenType
import com.durian.tssparty.presentation.components.BottomNavItem
import com.durian.tssparty.presentation.components.TssBottomNavigation
import com.durian.tssparty.presentation.screens.*
import com.durian.tssparty.presentation.viewmodel.MainViewModel
import com.durian.tssparty.presentation.viewmodel.ConnectionTestResult as ViewModelConnectionTestResult
import com.durian.tssparty.ui.theme.TssPartyTheme
import dagger.hilt.android.AndroidEntryPoint
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            TssPartyTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    TssPartyApp(
                        onCopyToClipboard = { text ->
                            val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
                            val clip = ClipData.newPlainText("邀请码", text)
                            clipboard.setPrimaryClip(clip)
                            Toast.makeText(this, "邀请码已复制", Toast.LENGTH_SHORT).show()
                        }
                    )
                }
            }
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TssPartyApp(
    viewModel: MainViewModel = hiltViewModel(),
    onCopyToClipboard: (String) -> Unit = {}
) {
    val navController = rememberNavController()
    val appState by viewModel.appState.collectAsState()
    val uiState by viewModel.uiState.collectAsState()
    val shares by viewModel.shares.collectAsState()
    val sessionStatus by viewModel.sessionStatus.collectAsState()
    val settings by viewModel.settings.collectAsState()
    val createdInviteCode by viewModel.createdInviteCode.collectAsState()
    val balances by viewModel.balances.collectAsState()
    val walletBalances by viewModel.walletBalances.collectAsState()
    val currentSessionId by viewModel.currentSessionId.collectAsState()
    val sessionParticipants by viewModel.sessionParticipants.collectAsState()
    val currentRound by viewModel.currentRound.collectAsState()
    val publicKey by viewModel.publicKey.collectAsState()
    val hasEnteredSession by viewModel.hasEnteredSession.collectAsState()

    // Transfer state
    val preparedTx by viewModel.preparedTx.collectAsState()
    val signSessionId by viewModel.signSessionId.collectAsState()
    val signInviteCode by viewModel.signInviteCode.collectAsState()
    val signParticipants by viewModel.signParticipants.collectAsState()
    val signCurrentRound by viewModel.signCurrentRound.collectAsState()
    val signature by viewModel.signature.collectAsState()
    val txHash by viewModel.txHash.collectAsState()

    // Join keygen state
    val joinSessionInfo by viewModel.joinSessionInfo.collectAsState()
    val joinKeygenParticipants by viewModel.joinKeygenParticipants.collectAsState()
    val joinKeygenRound by viewModel.joinKeygenRound.collectAsState()
    val joinKeygenPublicKey by viewModel.joinKeygenPublicKey.collectAsState()

    // CoSign state
    val coSignSessionInfo by viewModel.coSignSessionInfo.collectAsState()
    val coSignParticipants by viewModel.coSignParticipants.collectAsState()
    val coSignRound by viewModel.coSignRound.collectAsState()
    val coSignSignature by viewModel.coSignSignature.collectAsState()

    // Settings test connection results
    val messageRouterTestResult by viewModel.messageRouterTestResult.collectAsState()
    val accountServiceTestResult by viewModel.accountServiceTestResult.collectAsState()
    val kavaApiTestResult by viewModel.kavaApiTestResult.collectAsState()

    // Export/Import state
    val exportResult by viewModel.exportResult.collectAsState()
    val importResult by viewModel.importResult.collectAsState()

    // Current transfer wallet
    var transferWalletId by remember { mutableStateOf<Long?>(null) }

    // Export/Import file handling
    val context = LocalContext.current
    var pendingExportJson by remember { mutableStateOf<String?>(null) }
    var pendingExportAddress by remember { mutableStateOf<String?>(null) }

    // File picker for saving backup
    val createDocumentLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.CreateDocument(ShareBackup.MIME_TYPE)
    ) { uri: Uri? ->
        uri?.let { targetUri ->
            pendingExportJson?.let { json ->
                try {
                    context.contentResolver.openOutputStream(targetUri)?.use { outputStream ->
                        outputStream.write(json.toByteArray(Charsets.UTF_8))
                    }
                    Toast.makeText(context, "备份文件已保存", Toast.LENGTH_SHORT).show()
                } catch (e: Exception) {
                    Toast.makeText(context, "保存失败: ${e.message}", Toast.LENGTH_LONG).show()
                }
                pendingExportJson = null
                pendingExportAddress = null
            }
        }
    }

    // File picker for importing backup
    val openDocumentLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.OpenDocument()
    ) { uri: Uri? ->
        uri?.let { sourceUri ->
            try {
                context.contentResolver.openInputStream(sourceUri)?.use { inputStream ->
                    val json = inputStream.bufferedReader().readText()
                    viewModel.importShareBackup(json)
                }
            } catch (e: Exception) {
                Toast.makeText(context, "读取文件失败: ${e.message}", Toast.LENGTH_LONG).show()
            }
        }
    }

    // Handle export result - trigger file save dialog
    LaunchedEffect(pendingExportJson) {
        pendingExportJson?.let { json ->
            val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
            val addressSuffix = pendingExportAddress?.take(8) ?: "wallet"
            val fileName = "tss_backup_${addressSuffix}_$timestamp.${ShareBackup.FILE_EXTENSION}"
            createDocumentLauncher.launch(fileName)
        }
    }

    // Handle import result - show toast
    LaunchedEffect(importResult) {
        importResult?.let { result ->
            when {
                result.isSuccess -> {
                    Toast.makeText(context, result.message ?: "导入成功", Toast.LENGTH_SHORT).show()
                    viewModel.clearExportImportResult()
                }
                result.error != null -> {
                    Toast.makeText(context, result.error, Toast.LENGTH_LONG).show()
                    viewModel.clearExportImportResult()
                }
            }
        }
    }

    // Track if startup is complete
    var startupComplete by remember { mutableStateOf(false) }

    // Handle success messages
    LaunchedEffect(uiState.successMessage) {
        if (uiState.successMessage != null) {
            // Navigate back to wallets on success
            navController.navigate(BottomNavItem.Wallets.route) {
                popUpTo(BottomNavItem.Wallets.route) { inclusive = true }
            }
            // Reset all session states so next time user enters a fresh state
            viewModel.resetSessionState()
            viewModel.resetJoinKeygenState()
            viewModel.resetCoSignState()
            viewModel.resetTransferState()
            viewModel.clearSuccess()
            viewModel.clearCreatedInviteCode()
        }
    }

    // Show startup check screen if not complete
    if (!startupComplete) {
        StartupCheckScreen(
            appState = appState,
            onEnterApp = { startupComplete = true },
            onRetry = { viewModel.checkAllServices() }
        )
        return
    }

    // Main app with bottom navigation
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val currentRoute = navBackStackEntry?.destination?.route ?: BottomNavItem.Wallets.route

    Scaffold(
        bottomBar = {
            TssBottomNavigation(
                currentRoute = currentRoute,
                onNavigate = { item ->
                    navController.navigate(item.route) {
                        // Pop up to the start destination to avoid building up a large stack
                        popUpTo(BottomNavItem.Wallets.route) {
                            saveState = true
                        }
                        // Avoid multiple copies of the same destination
                        launchSingleTop = true
                        // Restore state when reselecting a previously selected item
                        restoreState = true
                    }
                }
            )
        }
    ) { paddingValues ->
        NavHost(
            navController = navController,
            startDestination = BottomNavItem.Wallets.route,
            modifier = Modifier.padding(paddingValues)
        ) {
            // Tab 1: My Wallets (我的钱包)
            composable(BottomNavItem.Wallets.route) {
                // Fetch balances when entering wallets screen
                LaunchedEffect(shares) {
                    viewModel.fetchAllBalances()
                }

                WalletsScreen(
                    shares = shares,
                    isConnected = uiState.isConnected,
                    balances = balances,
                    walletBalances = walletBalances,
                    networkType = settings.networkType,
                    onDeleteShare = { viewModel.deleteShare(it) },
                    onRefreshBalance = { address -> viewModel.fetchBalance(address) },
                    onTransfer = { shareId ->
                        transferWalletId = shareId
                        navController.navigate("transfer/$shareId")
                    },
                    onExportBackup = { shareId, _ ->
                        // Get address for filename
                        val share = shares.find { it.id == shareId }
                        pendingExportAddress = share?.address
                        // Export and save to file
                        viewModel.exportShareBackup(shareId) { json ->
                            pendingExportJson = json
                        }
                    },
                    onImportBackup = {
                        // Open file picker to select backup file
                        openDocumentLauncher.launch(arrayOf("*/*"))
                    },
                    onCreateWallet = {
                        navController.navigate(BottomNavItem.Create.route)
                    }
                )
            }

            // Transfer Screen
            composable("transfer/{shareId}") { backStackEntry ->
                val shareId = backStackEntry.arguments?.getString("shareId")?.toLongOrNull()
                val wallet = shareId?.let { viewModel.getWalletById(it) }

                if (wallet != null) {
                    TransferScreen(
                        wallet = wallet,
                        balance = balances[wallet.address],
                        walletBalance = walletBalances[wallet.address],
                        sessionStatus = sessionStatus,
                        participants = signParticipants,
                        currentRound = signCurrentRound,
                        totalRounds = 9,
                        preparedTx = preparedTx,
                        signSessionId = signSessionId,
                        inviteCode = signInviteCode,
                        signature = signature,
                        txHash = txHash,
                        isLoading = uiState.isLoading,
                        error = uiState.error,
                        networkType = settings.networkType,
                        rpcUrl = settings.kavaRpcUrl,
                        onPrepareTransaction = { toAddress, amount, tokenType ->
                            viewModel.prepareTransfer(shareId, toAddress, amount, tokenType)
                        },
                        onConfirmTransaction = {
                            viewModel.initiateSignSession(shareId, "")
                        },
                        onCopyInviteCode = {
                            signInviteCode?.let { onCopyToClipboard(it) }
                        },
                        onBroadcastTransaction = {
                            viewModel.broadcastTransaction()
                        },
                        onCancel = {
                            viewModel.resetTransferState()
                            viewModel.clearError()
                            navController.popBackStack()
                        },
                        onBackToWallets = {
                            viewModel.resetTransferState()
                            navController.navigate(BottomNavItem.Wallets.route) {
                                popUpTo(BottomNavItem.Wallets.route) { inclusive = true }
                            }
                        }
                    )
                }
            }

            // Tab 2: Create Wallet (创建钱包)
            composable(BottomNavItem.Create.route) {
                CreateWalletScreen(
                    isLoading = uiState.isLoading,
                    error = uiState.error,
                    inviteCode = createdInviteCode,
                    sessionId = currentSessionId,
                    sessionStatus = sessionStatus,
                    hasEnteredSession = hasEnteredSession,
                    participants = sessionParticipants,
                    currentRound = currentRound,
                    totalRounds = 9,
                    publicKey = publicKey,
                    countdownSeconds = uiState.countdownSeconds,
                    onCreateSession = { name, t, n, participantName ->
                        viewModel.createKeygenSession(name, t, n, participantName)
                    },
                    onCopyInviteCode = {
                        createdInviteCode?.let { onCopyToClipboard(it) }
                    },
                    onEnterSession = {
                        viewModel.enterSession()
                    },
                    onCancel = {
                        viewModel.cancelSession()
                        viewModel.clearError()
                        viewModel.resetSessionState()
                        navController.navigate(BottomNavItem.Wallets.route) {
                            popUpTo(BottomNavItem.Wallets.route) { inclusive = true }
                        }
                    },
                    onBackToHome = {
                        viewModel.resetSessionState()
                        navController.navigate(BottomNavItem.Wallets.route) {
                            popUpTo(BottomNavItem.Wallets.route) { inclusive = true }
                        }
                    }
                )
            }

            // Tab 3: Join Keygen (加入创建)
            composable(BottomNavItem.JoinKeygen.route) {
                // Convert JoinKeygenSessionInfo to JoinSessionInfo for the screen
                val screenSessionInfo = joinSessionInfo?.let {
                    JoinSessionInfo(
                        sessionId = it.sessionId,
                        walletName = it.walletName,
                        thresholdT = it.thresholdT,
                        thresholdN = it.thresholdN,
                        initiator = it.initiator,
                        currentParticipants = it.currentParticipants,
                        totalParticipants = it.totalParticipants
                    )
                }

                JoinKeygenScreen(
                    sessionStatus = sessionStatus,
                    isLoading = uiState.isLoading,
                    error = uiState.error,
                    sessionInfo = screenSessionInfo,
                    participants = joinKeygenParticipants,
                    currentRound = joinKeygenRound,
                    totalRounds = 9,
                    publicKey = joinKeygenPublicKey,
                    countdownSeconds = uiState.countdownSeconds,
                    onValidateInviteCode = { inviteCode ->
                        viewModel.validateInviteCode(inviteCode)
                    },
                    onJoinKeygen = { inviteCode, password ->
                        viewModel.joinKeygen(inviteCode, password)
                    },
                    onCancel = {
                        // Cancel from input screen - navigate away
                        viewModel.cancelSession()
                        viewModel.clearError()
                        viewModel.resetJoinKeygenState()
                        navController.navigate(BottomNavItem.Wallets.route) {
                            popUpTo(BottomNavItem.Wallets.route) { inclusive = true }
                        }
                    },
                    onResetState = {
                        // Reset from confirm/joining/progress screens - stay on page
                        viewModel.cancelSession()
                        viewModel.clearError()
                        viewModel.resetJoinKeygenState()
                    },
                    onBackToHome = {
                        viewModel.resetJoinKeygenState()
                        navController.navigate(BottomNavItem.Wallets.route) {
                            popUpTo(BottomNavItem.Wallets.route) { inclusive = true }
                        }
                    }
                )
            }

            // Tab 4: Co-Sign (参与签名)
            composable(BottomNavItem.CoSign.route) {
                // Convert CoSignSessionInfo to SignSessionInfo for the screen
                val screenSignSessionInfo = coSignSessionInfo?.let {
                    SignSessionInfo(
                        sessionId = it.sessionId,
                        keygenSessionId = it.keygenSessionId,
                        walletName = it.walletName,
                        messageHash = it.messageHash,
                        thresholdT = it.thresholdT,
                        thresholdN = it.thresholdN,
                        currentParticipants = it.currentParticipants
                    )
                }

                CoSignJoinScreen(
                    shares = shares,
                    sessionStatus = sessionStatus,
                    isLoading = uiState.isLoading,
                    error = uiState.error,
                    signSessionInfo = screenSignSessionInfo,
                    participants = coSignParticipants,
                    currentRound = coSignRound,
                    totalRounds = 9,
                    signature = coSignSignature,
                    countdownSeconds = uiState.countdownSeconds,
                    onValidateInviteCode = { inviteCode ->
                        viewModel.validateSignInviteCode(inviteCode)
                    },
                    onJoinSign = { inviteCode, shareId, password ->
                        viewModel.joinSign(inviteCode, shareId, password)
                    },
                    onCancel = {
                        // Cancel from input screen - navigate away
                        viewModel.cancelSession()
                        viewModel.clearError()
                        viewModel.resetCoSignState()
                        navController.navigate(BottomNavItem.Wallets.route) {
                            popUpTo(BottomNavItem.Wallets.route) { inclusive = true }
                        }
                    },
                    onResetState = {
                        // Reset from select_share/joining/signing screens - stay on page
                        viewModel.cancelSession()
                        viewModel.clearError()
                        viewModel.resetCoSignState()
                    },
                    onBackToHome = {
                        viewModel.resetCoSignState()
                        navController.navigate(BottomNavItem.Wallets.route) {
                            popUpTo(BottomNavItem.Wallets.route) { inclusive = true }
                        }
                    }
                )
            }

            // Tab 5: Settings (设置)
            composable(BottomNavItem.Settings.route) {
                // Convert ViewModel ConnectionTestResult to Screen ConnectionTestResult
                val screenMessageRouterStatus: ConnectionTestResult? = messageRouterTestResult?.let {
                    ConnectionTestResult(
                        success = it.success,
                        message = it.message,
                        latency = it.latency
                    )
                }
                val screenAccountServiceStatus: ConnectionTestResult? = accountServiceTestResult?.let {
                    ConnectionTestResult(
                        success = it.success,
                        message = it.message,
                        latency = it.latency
                    )
                }
                val screenKavaApiStatus: ConnectionTestResult? = kavaApiTestResult?.let {
                    ConnectionTestResult(
                        success = it.success,
                        message = it.message,
                        latency = it.latency
                    )
                }

                SettingsScreen(
                    settings = settings,
                    isConnected = uiState.isConnected,
                    messageRouterStatus = screenMessageRouterStatus,
                    accountServiceStatus = screenAccountServiceStatus,
                    kavaApiStatus = screenKavaApiStatus,
                    onSaveSettings = { newSettings ->
                        viewModel.updateSettings(newSettings)
                    },
                    onTestMessageRouter = { url ->
                        viewModel.testMessageRouter(url)
                    },
                    onTestAccountService = { url ->
                        viewModel.testAccountService(url)
                    },
                    onTestKavaApi = { url ->
                        viewModel.testKavaApi(url)
                    }
                )
            }
        }
    }
}
