import { useEffect, useMemo, useRef } from "react";
import {
  useExternalStoreRuntime,
  type ThreadMessage,
  type AppendMessage,
  type ExternalStoreAdapter,
} from "@assistant-ui/react";

export interface PaperclipIssueRuntimeReassignment {
  assigneeAgentId: string | null;
  assigneeUserId: string | null;
}

export interface PaperclipIssueRuntimeSendOptions {
  body: string;
  reopen?: boolean;
  reassignment?: PaperclipIssueRuntimeReassignment;
}

interface UsePaperclipIssueRuntimeOptions {
  messages: readonly ThreadMessage[];
  isRunning: boolean;
  onSend: (options: PaperclipIssueRuntimeSendOptions) => Promise<void>;
  onCancel?: (() => Promise<void>) | undefined;
}

function asRecord(value: unknown): Record<string, unknown> | null {
  if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
  return value as Record<string, unknown>;
}

function readTextContent(message: AppendMessage) {
  return message.content
    .filter((part): part is Extract<(typeof message.content)[number], { type: "text" }> => part.type === "text")
    .map((part) => part.text)
    .join("")
    .trim();
}

export function usePaperclipIssueRuntime({
  messages,
  isRunning,
  onSend,
  onCancel,
}: UsePaperclipIssueRuntimeOptions) {
  const onSendRef = useRef(onSend);
  const onCancelRef = useRef(onCancel);

  useEffect(() => {
    onSendRef.current = onSend;
  }, [onSend]);

  useEffect(() => {
    onCancelRef.current = onCancel;
  }, [onCancel]);

  const adapter = useMemo<ExternalStoreAdapter<ThreadMessage>>(() => ({
    messages,
    isRunning,
    onNew: async (message) => {
      const body = readTextContent(message);
      if (!body) return;

      const custom = asRecord(message.runConfig?.custom);
      const reassignmentRecord = asRecord(custom?.reassignment);
      const reassignment =
        reassignmentRecord &&
        ("assigneeAgentId" in reassignmentRecord || "assigneeUserId" in reassignmentRecord)
          ? {
              assigneeAgentId:
                typeof reassignmentRecord.assigneeAgentId === "string" ? reassignmentRecord.assigneeAgentId : null,
              assigneeUserId:
                typeof reassignmentRecord.assigneeUserId === "string" ? reassignmentRecord.assigneeUserId : null,
            }
          : undefined;

      await onSendRef.current({
        body,
        reopen: custom?.reopen === true ? true : undefined,
        reassignment,
      });
    },
    ...(onCancel ? {
      onCancel: async () => {
        await onCancelRef.current?.();
      },
    } : {}),
  }), [messages, isRunning, !!onCancel]);

  return useExternalStoreRuntime(adapter);
}
