"use client";

import { useCallback } from "react";
import { useAui } from "@assistant-ui/store";
import { flushTapSync } from "@assistant-ui/tap";
import { useComposerSend } from "@assistant-ui/core/react";
import type { ComposerSendOptions } from "@assistant-ui/core/store";
import {
  type TriggerPopoverAriaProps,
  useComposerInputDisabled,
  useComposerInputValue,
  useTriggerPopoverAriaProps,
} from "../primitives/composer/useComposerInputState";

/** @deprecated Experimental since 2026-06-23. Not scheduled for removal; the API may change in any release. */
export type Unstable_UseComposerInputOptions = {
  /**
   * Disables the input in addition to the composer's own disabled sources
   * (thread disabled, active dictation). When disabled, `isDisabled` is `true`
   * and `canSend` is `false`.
   */
  disabled?: boolean | undefined;
};

/** @deprecated Experimental since 2026-06-23. Not scheduled for removal; the API may change in any release. */
export type Unstable_ComposerInput = {
  /** Current composer text, or `""` when the composer is not editing. */
  value: string;
  /**
   * Writes `text` into the composer, mirroring `ComposerPrimitive.Input`:
   * a no-op unless the composer is editing; the controlled value stays in
   * sync within the same tick.
   */
  setText(text: string): void;
  /**
   * Sends the current message when `canSend` is `true`; otherwise a no-op.
   * Accepts the same options as the composer send action.
   */
  send(options?: ComposerSendOptions): void;
  /**
   * Whether the input is disabled, combining the `disabled` option with the
   * composer's own disabled sources (thread disabled, active dictation).
   */
  isDisabled: boolean;
  /**
   * Whether a send is currently available. Matches `ComposerPrimitive.Send`
   * gating (non-empty editing composer, not running without queue support) and
   * is additionally `false` while `isDisabled`.
   */
  canSend: boolean;
};

/**
 * Headless bridge to the composer's text value and send action, for building a
 * custom composer input without `ComposerPrimitive.Input`. It is a thin bridge,
 * not a second input: it does not own keyboard behavior, autosize, IME or
 * contentEditable sync, paste/drop attachments, focus management, or rich-text
 * state. Spread `unstable_useTriggerPopoverAriaProps()` onto your element for
 * trigger-popover combobox semantics.
 *
 * @deprecated Experimental since 2026-06-23. Not scheduled for removal; the API may change in any release.
 *
 * @example
 * ```tsx
 * const { value, setText, send, isDisabled, canSend } = unstable_useComposerInput();
 * <textarea
 *   value={value}
 *   disabled={isDisabled}
 *   onChange={(e) => setText(e.target.value)}
 *   onKeyDown={(e) => {
 *     if (e.nativeEvent.isComposing || e.keyCode === 229) return;
 *
 *     if (e.key === "Enter" && !e.shiftKey && canSend) {
 *       e.preventDefault();
 *       send();
 *     }
 *   }}
 * />
 * ```
 */
export function unstable_useComposerInput(
  options?: Unstable_UseComposerInputOptions,
): Unstable_ComposerInput {
  const aui = useAui();
  const value = useComposerInputValue();
  const isDisabled = useComposerInputDisabled(options?.disabled);

  const setText = useCallback(
    (text: string) => {
      if (!aui.composer.getState().isEditing) return;
      flushTapSync(() => {
        aui.composer.setText(text, { origin: "user" });
      });
    },
    [aui],
  );

  const { send: rawSend, disabled: sendDisabled } = useComposerSend();
  const canSend = !sendDisabled && !isDisabled;
  const send = useCallback(
    (sendOptions?: ComposerSendOptions) => {
      if (!canSend) return;
      rawSend(sendOptions);
    },
    [canSend, rawSend],
  );

  return { value, setText, send, isDisabled, canSend };
}

/** @deprecated Experimental since 2026-06-23. Not scheduled for removal; the API may change in any release. */
export type Unstable_TriggerPopoverAriaProps = TriggerPopoverAriaProps;

/**
 * ARIA combobox attributes for the focused element (typically the composer
 * input) describing the open trigger popover, per the WAI-ARIA editable
 * combobox pattern. Returns an empty object outside a `TriggerPopoverRoot` or
 * when no popover is open. Spread these last so they take precedence over any
 * matching ARIA props you set yourself, mirroring `ComposerPrimitive.Input`.
 *
 * @deprecated Experimental since 2026-06-23. Not scheduled for removal; the API may change in any release.
 *
 * @example
 * ```tsx
 * const aria = unstable_useTriggerPopoverAriaProps();
 * <textarea {...aria} />
 * ```
 */
export function unstable_useTriggerPopoverAriaProps(): Unstable_TriggerPopoverAriaProps {
  return useTriggerPopoverAriaProps();
}
