@file:OptIn(ExperimentalMaterial3AdaptiveApi::class)

package wang.yaojia.webterm.nav

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController
import wang.yaojia.webterm.components.ContinueLastBanner
import wang.yaojia.webterm.components.continueLastModel
import wang.yaojia.webterm.screens.AdaptiveHome
import wang.yaojia.webterm.screens.SessionListScreen
import wang.yaojia.webterm.viewmodels.ApiClientSessionGateway
import wang.yaojia.webterm.viewmodels.SessionListViewModel
import wang.yaojia.webterm.wiring.AppEnvironment
import java.util.UUID

/**
 * The sessions landing (A20) inside the A26 adaptive shell: a [SessionListScreen] (list pane) beside the
 * live [TerminalHost] (detail pane) on large screens, or a single list on compact where a row tap pushes
 * the terminal destination. The [ContinueLastBanner] (A29) is layered above the list. The navigation-suite
 * "项目" entry navigates to [ProjectsHome].
 *
 * ### Adaptive open behaviour
 * On [LayoutMode.LIST_DETAIL] a row tap fills the detail pane (a per-session holder keyed under THIS
 * back-stack entry); on [LayoutMode.STACK] it pushes a full-screen terminal destination. New-session and
 * continue-last always push, so a fresh spawn gets its own nav-scoped holder.
 *
 * The [SessionListViewModel] host menu drives its own active-host selection; this pane reads the resolved
 * active host id from its state to build the terminal endpoint / continue-last pointer.
 */
@Composable
public fun SessionsHome(
    env: AppEnvironment,
    navController: NavHostController,
    modifier: Modifier = Modifier,
) {
    val viewModel = remember(env) {
        SessionListViewModel(
            hostStore = env.hostStore,
            gatewayFactory = { host -> ApiClientSessionGateway(env.apiClientFactory.create(host.endpoint)) },
        )
    }
    val state by viewModel.uiState.collectAsStateWithLifecycle()
    val activeHostId = state.activeHostId

    val sizeClass = currentWindowAdaptiveInfo().windowSizeClass
    val mode = LayoutPolicy.mode(windowWidthOf(sizeClass))
    var selectedSessionId by rememberSaveable { mutableStateOf<String?>(null) }

    val openSession: (UUID) -> Unit = { id ->
        val sid = id.toString()
        if (mode == LayoutMode.LIST_DETAIL) {
            selectedSessionId = sid
        } else {
            activeHostId?.let { navController.navigate(NavRoutes.terminal(it, sid)) }
        }
    }
    val openNewSession: () -> Unit = {
        activeHostId?.let { navController.navigate(NavRoutes.terminalNew(it)) }
    }

    AdaptiveHome(
        listPane = {
            Column(modifier = Modifier.fillMaxSize()) {
                val lastSessionId by produceState<String?>(initialValue = null, key1 = activeHostId) {
                    value = activeHostId?.let { runCatchingCancellable { env.lastSessionStore.lastSessionId(it) }.getOrNull() }
                }
                ContinueLastBanner(
                    model = continueLastModel(lastSessionId),
                    onContinue = { sid -> activeHostId?.let { navController.navigate(NavRoutes.terminal(it, sid)) } },
                )
                Box(modifier = Modifier.weight(1f)) {
                    SessionListScreen(
                        viewModel = viewModel,
                        onOpenSession = openSession,
                        onNewSession = openNewSession,
                        onPairHost = { navController.navigate(NavRoutes.PAIRING) },
                        onEnroll = { navController.navigate(NavRoutes.ENROLL) },
                        onImportCert = { navController.navigate(NavRoutes.CERT) },
                    )
                }
            }
        },
        detailPane = {
            val sid = selectedSessionId
            if (sid != null && activeHostId != null) {
                TerminalHost(
                    env = env,
                    hostId = activeHostId,
                    sessionArg = sid,
                    cwd = null,
                    onNewSessionInCwd = { req ->
                        navController.navigate(newTerminalRoute(activeHostId, req.cwd))
                    },
                    holderKey = "detail/$activeHostId/$sid",
                )
            } else {
                DetailPlaceholder("选择一个会话查看终端。")
            }
        },
        selectedDestination = 0,
        onSelectDestination = { index ->
            if (index == 1) navController.navigate(NavRoutes.PROJECTS) { launchSingleTop = true }
        },
        windowSizeClass = sizeClass,
        modifier = modifier,
    )
}
