import { resource, tapEffectEvent, tapResource } from "@assistant-ui/tap";
import type {
  Unstable_TriggerAdapter,
  Unstable_TriggerCategory,
  Unstable_TriggerItem,
} from "@assistant-ui/core";
import type { AssistantClient } from "@assistant-ui/store";
import { TriggerDetectionResource } from "./triggerDetectionResource";
import { TriggerKeyboardResource } from "./triggerKeyboardResource";
import { TriggerNavigationResource } from "./triggerNavigationResource";
import {
  TriggerSelectionResource,
  type SelectItemOverride,
  type TriggerBehavior,
} from "./triggerSelectionResource";

export type { SelectItemOverride, TriggerBehavior };
export type { TriggerPopoverKeyEvent } from "./triggerKeyboardResource";

/** @deprecated Use `TriggerBehavior`. */
export type OnSelectBehavior = TriggerBehavior;

export type TriggerPopoverResourceOutput = {
  readonly open: boolean;
  readonly query: string;
  readonly activeCategoryId: string | null;
  readonly categories: readonly Unstable_TriggerCategory[];
  readonly items: readonly Unstable_TriggerItem[];
  readonly highlightedIndex: number;
  readonly isSearchMode: boolean;
  /** Stable ID prefix for generating accessible element IDs. */
  readonly popoverId: string;
  /** ID of the currently highlighted item (for aria-activedescendant). */
  readonly highlightedItemId: string | undefined;

  selectCategory(categoryId: string): void;
  goBack(): void;
  selectItem(item: Unstable_TriggerItem): void;
  close(): void;
  /** Move the highlight to an entry index (e.g. from pointer hover). Out-of-range values are ignored. */
  highlightIndex(index: number): void;
  handleKeyDown(e: {
    readonly key: string;
    readonly shiftKey: boolean;
    preventDefault(): void;
  }): boolean;

  setCursorPosition(pos: number): void;
  registerSelectItemOverride(fn: SelectItemOverride): () => void;
};

/** Composes detection, navigation, keyboard, and selection sub-resources. */
export const TriggerPopoverResource = resource(
  ({
    adapter,
    text,
    triggerChar,
    behavior,
    aui,
    popoverId,
  }: {
    adapter: Unstable_TriggerAdapter | undefined;
    text: string;
    triggerChar: string;
    behavior: TriggerBehavior | undefined;
    aui: AssistantClient;
    /** Stable ID for accessible element IDs (pass React's useId() from component layer). */
    popoverId: string;
  }): TriggerPopoverResourceOutput => {
    const detection = tapResource(
      TriggerDetectionResource({ text, triggerChar }),
    );

    const open =
      detection.trigger !== null &&
      adapter !== undefined &&
      behavior !== undefined;

    const navigation = tapResource(
      TriggerNavigationResource({
        adapter,
        query: detection.query,
        open,
      }),
    );

    const onSelected = tapEffectEvent(() => {
      navigation.goBack();
    });

    const selection = tapResource(
      TriggerSelectionResource({
        behavior,
        trigger: detection.trigger,
        aui,
        triggerChar,
        setCursorPosition: detection.setCursorPosition,
        onSelected,
      }),
    );

    const keyboard = tapResource(
      TriggerKeyboardResource({
        navigableList: navigation.navigableList,
        isSearchMode: navigation.isSearchMode,
        activeCategoryId: navigation.activeCategoryId,
        query: detection.query,
        popoverId,
        open,
        selectItem: selection.selectItem,
        selectCategory: navigation.selectCategory,
        goBack: navigation.goBack,
        close: selection.close,
      }),
    );

    return {
      open,
      query: detection.query,
      activeCategoryId: navigation.activeCategoryId,
      categories: navigation.categories,
      items: navigation.items,
      highlightedIndex: keyboard.highlightedIndex,
      isSearchMode: navigation.isSearchMode,
      popoverId,
      highlightedItemId: keyboard.highlightedItemId,
      selectCategory: navigation.selectCategory,
      goBack: navigation.goBack,
      selectItem: selection.selectItem,
      close: selection.close,
      highlightIndex: keyboard.highlightIndex,
      handleKeyDown: keyboard.handleKeyDown,
      setCursorPosition: detection.setCursorPosition,
      registerSelectItemOverride: selection.registerSelectItemOverride,
    };
  },
);
