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

package org.signal.mediasend.screens.edit

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import org.signal.core.ui.compose.DayNightPreviews
import org.signal.core.ui.compose.DropdownMenus
import org.signal.core.ui.compose.IconButtons
import org.signal.core.ui.compose.Previews
import org.signal.core.ui.compose.SignalIcons
import org.signal.core.ui.compose.theme.SignalTheme
import org.signal.mediasend.R
import org.signal.mediasend.test.TestTags

/** Mirrors the legacy send button's disabled tint, which has no equivalent in the core-ui color scheme. */
private val DisabledNextButtonColor = Color(0xFF777777)

/**
 * Because we need to be able to support stuff like mentions, styled text, and custom emoji, we need to allow
 * the users of this feature to inject their own text-field.
 */
val LocalAddAMessageRowTextField = compositionLocalOf<@Composable (CharSequence, Modifier) -> Unit> {
  { message, modifier ->
    Text(
      text = message.toString(),
      style = MaterialTheme.typography.bodyLarge,
      color = MaterialTheme.colorScheme.onSurfaceVariant,
      modifier = modifier
    )
  }
}

/**
 * @param recipientChatColor The chat color of the single recipient this media is headed to, or null when the destination
 *   is still to be chosen. Non-null makes the trailing button a chat-color-tinted send button rather than a themed
 *   "next" arrow.
 */
@Composable
fun AddAMessageRow(
  message: CharSequence?,
  onEvent: (MediaEditScreenEvents) -> Unit,
  onNextClick: () -> Unit,
  modifier: Modifier = Modifier,
  enabled: Boolean = true,
  canScheduleSend: Boolean = false,
  viewOnceAvailable: Boolean = false,
  viewOnce: Boolean = false,
  recipientChatColor: Color? = null
) {
  Row(
    horizontalArrangement = Arrangement.Center,
    verticalAlignment = Alignment.CenterVertically,
    modifier = modifier
  ) {
    Row(
      verticalAlignment = Alignment.CenterVertically,
      modifier = Modifier
        .background(color = MaterialTheme.colorScheme.surfaceVariant, shape = RoundedCornerShape(percent = 50))
        .weight(1f)
        .heightIn(min = 40.dp)
        .then(
          if (viewOnce) {
            // A view-once send cannot carry a body, so the row becomes a static label rather than an entry point.
            Modifier
          } else {
            Modifier.clickable(enabled = enabled, onClickLabel = stringResource(R.string.AddAMessageRow__add_a_message), onClick = { onEvent(MediaEditScreenEvents.AddMessageClick()) }, role = Role.Button)
          }
        )
    ) {
      if (viewOnce) {
        Text(
          text = stringResource(R.string.AddAMessageRow__view_once_media),
          style = MaterialTheme.typography.bodyLarge,
          color = MaterialTheme.colorScheme.onSurfaceVariant,
          textAlign = TextAlign.Center,
          modifier = Modifier
            .weight(1f)
            .padding(horizontal = 16.dp)
        )
      } else {
        IconButtons.IconButton(
          enabled = enabled,
          onClick = { onEvent(MediaEditScreenEvents.AddMessageClick(startWithEmojiKeyboard = true)) }
        ) {
          Icon(
            painter = SignalIcons.Emoji.painter,
            contentDescription = stringResource(R.string.AddAMessageRow__open_emoji_keyboard)
          )
        }

        LocalAddAMessageRowTextField.current(
          message ?: stringResource(R.string.AddAMessageRow__message),
          Modifier
            .weight(1f)
            .padding(end = if (viewOnceAvailable) 0.dp else 16.dp)
        )
      }

      if (viewOnceAvailable) {
        IconButtons.IconButton(
          enabled = enabled,
          onClick = { onEvent(MediaEditScreenEvents.ToggleViewOnce) }
        ) {
          Icon(
            painter = if (viewOnce) SignalIcons.ViewOnce.painter else SignalIcons.ViewOnceInfinite.painter,
            contentDescription = stringResource(R.string.AddAMessageRow__toggle_view_once)
          )
        }
      }
    }

    Box {
      val scheduleSendMenuController = remember { DropdownMenus.MenuController() }

      IconButtons.IconButton(
        enabled = enabled,
        onClick = onNextClick,
        onLongClick = if (canScheduleSend) scheduleSendMenuController::show else null,
        onLongClickLabel = stringResource(R.string.AddAMessageRow__schedule_send),
        colors = IconButtons.iconButtonColors(
          containerColor = recipientChatColor ?: MaterialTheme.colorScheme.onSecondaryContainer,
          contentColor = if (recipientChatColor != null) SignalTheme.colors.colorOnCustom else MaterialTheme.colorScheme.secondaryContainer,
          disabledContainerColor = DisabledNextButtonColor,
          disabledContentColor = MaterialTheme.colorScheme.secondaryContainer
        ),
        modifier = Modifier
          .testTag(TestTags.ADD_A_MESSAGE_NEXT_BUTTON)
          .padding(start = 12.dp)
      ) {
        Icon(
          painter = if (recipientChatColor != null) SignalIcons.SendFill.painter else SignalIcons.ArrowEnd.painter,
          contentDescription = stringResource(if (recipientChatColor != null) R.string.AddAMessageRow__send else R.string.AddAMessageRow__next)
        )
      }

      ScheduleSendMenu(
        controller = scheduleSendMenuController,
        onOptionClick = { onEvent(MediaEditScreenEvents.ScheduleSendClick(it)) }
      )
    }
  }
}

@DayNightPreviews
@Composable
private fun AddAMessageRowPreview() {
  Previews.Preview {
    AddAMessageRow(
      message = null,
      onEvent = {},
      onNextClick = {}
    )
  }
}

@DayNightPreviews
@Composable
private fun AddAMessageRowViewOnceAvailablePreview() {
  Previews.Preview {
    AddAMessageRow(
      message = null,
      onEvent = {},
      onNextClick = {},
      viewOnceAvailable = true
    )
  }
}

@DayNightPreviews
@Composable
private fun AddAMessageRowViewOncePreview() {
  Previews.Preview {
    AddAMessageRow(
      message = null,
      onEvent = {},
      onNextClick = {},
      viewOnceAvailable = true,
      viewOnce = true
    )
  }
}

@DayNightPreviews
@Composable
private fun AddAMessageRowKnownRecipientPreview() {
  Previews.Preview {
    AddAMessageRow(
      message = null,
      onEvent = {},
      onNextClick = {},
      recipientChatColor = Color(0xFF3B7845)
    )
  }
}

@DayNightPreviews
@Composable
private fun AddAMessageRowDisabledPreview() {
  Previews.Preview {
    AddAMessageRow(
      message = null,
      onEvent = {},
      onNextClick = {},
      enabled = false,
      recipientChatColor = Color(0xFF3B7845)
    )
  }
}
