import { AppendMessage, ThreadMessage } from "../../types";
import { AttachmentAdapter } from "../attachment";
import {
  AddToolResultOptions,
  ThreadSuggestion,
} from "../core/ThreadRuntimeCore";
import { FeedbackAdapter } from "../feedback/FeedbackAdapter";
import { SpeechSynthesisAdapter } from "../speech/SpeechAdapterTypes";
import { ThreadListMetadata } from "../core/ThreadListRuntimeCore";
import { ThreadMessageLike } from "./ThreadMessageLike";

export type ExternalStoreThreadListAdapter = {
  threadId?: string | undefined;
  threads?: readonly ThreadListMetadata[] | undefined;
  archivedThreads?: readonly ThreadListMetadata[] | undefined;
  onSwitchToNewThread?: (() => Promise<void> | void) | undefined;
  onSwitchToThread?: ((threadId: string) => Promise<void> | void) | undefined;
  onRename?: (
    threadId: string,
    newTitle: string,
  ) => (Promise<void> | void) | undefined;
  onArchive?: ((threadId: string) => Promise<void> | void) | undefined;
  onUnarchive?: ((threadId: string) => Promise<void> | void) | undefined;
  onDelete?: ((threadId: string) => Promise<void> | void) | undefined;
};

export type ExternalStoreMessageConverter<T> = (
  message: T,
  idx: number,
) => ThreadMessageLike;

type ExternalStoreMessageConverterAdapter<T> = {
  convertMessage: ExternalStoreMessageConverter<T>;
};

type ExternalStoreAdapterBase<T> = {
  /**
   * @deprecated Use `adapterst.threadList.threadId` instead. This will be removed in 0.6.0.
   */
  threadId?: string | undefined;

  /**
   * @deprecated Use `adapters..threadList.onSwitchToThread` instead. This will be removed in 0.6.0.
   */
  onSwitchToThread?: ((threadId: string) => Promise<void> | void) | undefined;
  /**
   * @deprecated Use `adapters.threadList.onSwitchToNewThread` instead. This will be removed in 0.6.0.
   */
  onSwitchToNewThread?: (() => Promise<void> | void) | undefined;

  isDisabled?: boolean | undefined;
  isRunning?: boolean | undefined;
  messages: T[];
  suggestions?: readonly ThreadSuggestion[] | undefined;
  extras?: unknown;

  setMessages?: ((messages: T[]) => void) | undefined;
  onNew: (message: AppendMessage) => Promise<void>;
  onEdit?: ((message: AppendMessage) => Promise<void>) | undefined;
  onReload?: ((parentId: string | null) => Promise<void>) | undefined;
  onCancel?: (() => Promise<void>) | undefined;
  onAddToolResult?:
    | ((options: AddToolResultOptions) => Promise<void> | void)
    | undefined;
  convertMessage?: ExternalStoreMessageConverter<T> | undefined;
  adapters?:
    | {
        attachments?: AttachmentAdapter | undefined;
        speech?: SpeechSynthesisAdapter | undefined;
        feedback?: FeedbackAdapter | undefined;
        threadList?: ExternalStoreThreadListAdapter | undefined;
      }
    | undefined;
  unstable_capabilities?:
    | {
        copy?: boolean | undefined;
      }
    | undefined;
};

export type ExternalStoreAdapter<T = ThreadMessage> =
  ExternalStoreAdapterBase<T> &
    (T extends ThreadMessage
      ? object
      : ExternalStoreMessageConverterAdapter<T>);
