/*
 * Copyright 2025 Signal Messenger, LLC
 * SPDX-License-Identifier: AGPL-3.0-only
 */

package org.thoughtcrime.securesms.main

import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalResources
import org.signal.core.ui.compose.AllDevicePreviews
import org.signal.core.ui.compose.Previews
import org.signal.core.ui.compose.Snackbars
import org.signal.core.ui.compose.showSnackbar
import org.signal.core.ui.isSplitPane
import org.signal.core.ui.rememberIsSplitPane
import org.thoughtcrime.securesms.components.snackbars.SnackbarHostKey
import org.thoughtcrime.securesms.components.snackbars.rememberSnackbarState
import org.thoughtcrime.securesms.megaphone.Megaphone
import org.thoughtcrime.securesms.megaphone.MegaphoneActionController
import org.thoughtcrime.securesms.megaphone.Megaphones
import org.thoughtcrime.securesms.window.NavigationType

interface MainBottomChromeCallback : MainFloatingActionButtonsCallback {
  fun onMegaphoneVisible(megaphone: Megaphone)
  fun onSnackbarDismissed()

  object Empty : MainBottomChromeCallback {
    override fun onNewChatClick() = Unit
    override fun onNewCallClick() = Unit
    override fun onCameraClick(destination: MainNavigationListLocation) = Unit
    override fun onMegaphoneVisible(megaphone: Megaphone) = Unit
    override fun onSnackbarDismissed() = Unit
  }
}

data class MainBottomChromeState(
  val destination: MainNavigationListLocation = MainNavigationListLocation.CHATS,
  val megaphoneState: MainMegaphoneState = MainMegaphoneState(),
  val mainToolbarMode: MainToolbarMode = MainToolbarMode.FULL
)

/**
 * Stack of bottom chrome components:
 * - The Floating Action buttons
 * - The megaphone view
 * - The snackbar
 */
@Composable
fun MainBottomChrome(
  state: MainBottomChromeState,
  callback: MainBottomChromeCallback,
  megaphoneActionController: MegaphoneActionController,
  modifier: Modifier = Modifier
) {
  val isSplitPane = LocalResources.current.rememberIsSplitPane()
  val navigationType = NavigationType.rememberNavigationType()

  Column(
    modifier = modifier
      .fillMaxWidth()
      .animateContentSize()
      .then(if (navigationType == NavigationType.RAIL) Modifier.navigationBarsPadding() else Modifier)
  ) {
    if (state.mainToolbarMode == MainToolbarMode.FULL && navigationType != NavigationType.RAIL) {
      Box(
        contentAlignment = Alignment.CenterEnd,
        modifier = Modifier.fillMaxWidth()
      ) {
        MainFloatingActionButtons(
          destination = state.destination,
          callback = callback
        )
      }
    }

    if (state.mainToolbarMode == MainToolbarMode.FULL) {
      MainMegaphoneContainer(
        state = state.megaphoneState,
        controller = megaphoneActionController,
        onMegaphoneVisible = callback::onMegaphoneVisible
      )
    }

    if (isSplitPane) {
      return@Column
    }

    val snackBarModifier = if (state.mainToolbarMode == MainToolbarMode.BASIC && navigationType != NavigationType.RAIL) {
      Modifier.navigationBarsPadding()
    } else {
      Modifier
    }

    MainSnackbar(
      onDismissed = callback::onSnackbarDismissed,
      modifier = snackBarModifier
    )
  }
}

@Composable
fun MainSnackbar(
  onDismissed: () -> Unit,
  modifier: Modifier = Modifier,
  hostKey: SnackbarHostKey = MainSnackbarHostKey.MainChrome
) {
  val hostState = remember { SnackbarHostState() }
  val stateHolder = rememberSnackbarState(hostKey)
  val snackbarState = stateHolder.value

  Snackbars.Host(
    hostState,
    modifier = modifier
  )

  LaunchedEffect(snackbarState) {
    if (snackbarState != null) {
      val result = hostState.showSnackbar(
        message = snackbarState.message,
        actionLabel = snackbarState.actionState?.action,
        duration = snackbarState.duration
      )

      when (result) {
        SnackbarResult.Dismissed -> Unit
        SnackbarResult.ActionPerformed -> snackbarState.actionState?.onActionClick?.invoke()
      }

      stateHolder.clear()
      onDismissed()
    }
  }
}

@AllDevicePreviews
@Composable
fun MainBottomChromePreview() {
  Previews.Preview {
    val megaphone = remember {
      Megaphone.Builder(Megaphones.Event.ONBOARDING, Megaphone.Style.ONBOARDING).build()
    }

    Box(
      contentAlignment = Alignment.BottomCenter,
      modifier = Modifier.fillMaxSize()
    ) {
      MainBottomChrome(
        state = MainBottomChromeState(
          megaphoneState = MainMegaphoneState(
            megaphone = megaphone
          )
        ),
        callback = MainBottomChromeCallback.Empty,
        megaphoneActionController = EmptyMegaphoneActionController
      )
    }
  }
}
