///|
const PromptBoxStyle : String = "display:flex;flex-direction:column;gap:8px;padding:12px;border:1px solid transparent;border-radius:var(--sumi-radius-xl,16px);background:var(--sumi-input-bg,rgba(34,34,34,0.72));backdrop-filter:blur(60px);-webkit-backdrop-filter:blur(60px);box-shadow:var(--sumi-shadow-float,0px 2px 6px 0px rgba(0,0,0,0.02),0px 4px 12px 0px rgba(0,0,0,0.06))"

///|
const PromptTextareaStyle : String = "display:block;width:100%;margin:0;padding:0;border:none;background:transparent;resize:none;font-size:14px;line-height:22px;color:var(--sumi-text,#ffffff);outline:none;appearance:none;-webkit-appearance:none"

///|
const PromptFooterStyle : String = "display:flex;align-items:center;justify-content:flex-end;gap:8px;width:100%"

///|
const SendButtonBaseStyle : String = "display:inline-flex;flex:none;align-items:center;justify-content:center;width:32px;height:32px;margin:0;padding:0;border:none;border-radius:9999px;cursor:pointer;user-select:none;appearance:none;-webkit-appearance:none;outline:none"

///|
const SendButtonEnabledStyle : String = "background:var(--sumi-primary-bg,#fafafa);color:var(--sumi-primary-fg,#1a1a1a)"

///|
const SendButtonDisabledStyle : String = "background:var(--sumi-primary-bg-disabled,rgba(204,221,255,0.16));color:var(--sumi-primary-fg-disabled,rgba(224,245,255,0.2))"

///|
/// The circular submit button used by `prompt_box`. Disabled state uses the
/// design's exact muted fill rather than opacity. `loading=true` keeps the
/// muted fill, swaps the arrow for a 20px spinner in the disabled tone, and
/// blocks clicks while a submission is in flight.
pub fn send_button(
  disabled? : Bool = false,
  loading? : Bool = false,
  on_click? : @cmd.Cmd,
  id? : String,
  class? : String,
  title? : String,
  aria_label? : String = "Send",
  attrs? : @html.Attrs,
  style? : Array[String] = [],
) -> @html.Html {
  let inactive = disabled || loading
  let element_attrs = @internal.sumi_attrs(attrs)
    .data_set("slot", "send-button")
    .aria_label(aria_label)
  if loading {
    ignore(element_attrs.aria_busy("true"))
  }
  let content : @html.Html = if loading {
    @primitives.spinner(size=20)
  } else {
    @primitives.icon_arrow_up(size=18)
  }
  @html.button(
    style=@internal.sumi_styles(
      [
        @internal.SumiBoxSizing,
        @internal.SumiTextRendering,
        @internal.SumiTransition,
        SendButtonBaseStyle,
        if inactive {
          SendButtonDisabledStyle
        } else {
          SendButtonEnabledStyle
        },
        @internal.sumi_disabled_style(inactive),
      ],
      style,
    ),
    type_="button",
    disabled=inactive,
    id?,
    class?,
    title?,
    on_click?,
    attrs=element_attrs,
    [content],
  )
}

///|
const PromptCountStyle : String = "flex:none;font-size:12px;line-height:20px;font-weight:500;font-variant-numeric:tabular-nums;color:var(--sumi-text-placeholder,rgba(255,255,255,0.35))"

///|
const PromptCountOverStyle : String = "color:var(--sumi-error,#ff3355)"

///|
/// The composite prompt input: a frosted, rounded container holding an
/// auto-sized textarea and a footer row (action slot + circular send
/// button). Controlled: the caller owns `value`.
///
/// `show_count=true` renders a `n / max` counter next to the send button;
/// it turns error-red once the value exceeds `maxlength`. The textarea
/// carries the library's thin-scrollbar styling.
///
/// ```moonbit nocheck
/// prompt_box(
///   value=prompt,
///   placeholder="Describe what to create",
///   on_input=emit.map(PromptChanged),
///   on_send=emit(Submit),
///   send_disabled=prompt.is_empty(),
///   maxlength=800,
///   show_count=true,
/// )
/// ```
pub fn prompt_box(
  value~ : String,
  placeholder? : String = "",
  rows? : Int = 1,
  on_input? : @internal.Emit[String],
  on_send? : @cmd.Cmd,
  send_disabled? : Bool = false,
  send_loading? : Bool = false,
  disabled? : Bool = false,
  maxlength? : Int,
  show_count? : Bool = false,
  autofocus? : Bool,
  actions? : @html.Html,
  id? : String,
  class? : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
) -> @html.Html {
  let element_attrs = @internal.sumi_attrs(attrs).data_set("slot", "prompt-box")
  let textarea = @html.textarea(
    value~,
    placeholder~,
    rows~,
    on_input?,
    disabled~,
    maxlength?,
    autofocus?,
    style=[
      @internal.SumiBoxSizing,
      @internal.SumiFontSans,
      @internal.SumiTextRendering,
      PromptTextareaStyle,
    ],
    attrs=@html.Attrs::build().data_set("slot", "prompt-textarea"),
    "",
  )
  let counter : @html.Html = if show_count {
    let limit = maxlength.unwrap_or(0)
    let over = limit > 0 && value.length() > limit
    @html.span(
      style=[
        @internal.SumiFontNum,
        PromptCountStyle,
        if over {
          PromptCountOverStyle
        } else {
          ""
        },
      ],
      attrs=@html.Attrs::build()
        .data_set("slot", "prompt-count")
        .aria_hidden("true"),
      "\{value.length()}/\{limit}",
    )
  } else {
    @html.nothing
  }
  let footer_left : @html.Html = match actions {
    Some(actions) =>
      @html.div(
        style=["display:flex;align-items:center;gap:4px;margin-right:auto"],
        attrs=@html.Attrs::build().data_set("slot", "prompt-actions"),
        [actions],
      )
    None => @html.nothing
  }
  @html.div(
    style=@internal.sumi_styles(
      [
        @internal.SumiBoxSizing,
        @internal.SumiFontSans,
        @internal.SumiTextRendering,
        PromptBoxStyle,
      ],
      style,
    ),
    id?,
    class?,
    attrs=element_attrs,
    [
      textarea,
      @html.div(style=[@internal.SumiBoxSizing, PromptFooterStyle], [
        footer_left,
        counter,
        send_button(
          disabled=send_disabled,
          loading=send_loading,
          on_click?=on_send,
        ),
      ]),
    ],
  )
}