import { marked } from "marked";
import { useRef } from "preact/hooks";
import type { JsonValue } from "../types";
import {
  callManualTool,
  callManualToolAsync,
  copyTextToClipboard,
  getManualToolJob,
  listManualTools,
  startManualToolCall,
  updateCardTemplateState,
  updateWorkbenchTemplateState,
} from "./api";
import type { RuntimeHost, RuntimeItem, RuntimeSurface } from "./runtimeTypes";
import { normalizeTemplateState, runtimeItemId } from "./runtimeUtils";
import {
  clearCardSelection,
  getCardLiveContent,
  getCardSelection,
  requestCardFeedRefresh,
  runCardRefresh,
  setCardLiveContent,
  setCardRefreshHandler,
  setCardSelection,
} from "./store";

export function useRuntimeHost(
  surface: RuntimeSurface,
  item: RuntimeItem,
  stateRef: { current: Record<string, JsonValue> },
  setState: (value: Record<string, JsonValue>) => void,
) {
  const itemRef = useRef(item);
  itemRef.current = item;

  const hostRef = useRef<RuntimeHost | null>(null);
  if (!hostRef.current) {
    hostRef.current = {
      surface,
      item,
      getState: () => normalizeTemplateState(stateRef.current),
      replaceState: async (nextState) => {
        const normalized = normalizeTemplateState(nextState);
        stateRef.current = normalized;
        setState(normalized);
        const currentItem = itemRef.current;
        if ("serverId" in currentItem) {
          if (!currentItem.serverId) throw new Error("card id is required");
          await updateCardTemplateState(currentItem.serverId, normalized);
        } else if ("chatId" in currentItem) {
          await updateWorkbenchTemplateState(currentItem, normalized);
        }
        return normalizeTemplateState(normalized);
      },
      patchState: async (patch) => {
        const nextState = { ...stateRef.current, ...normalizeTemplateState(patch) };
        return hostRef.current?.replaceState(nextState) ?? normalizeTemplateState(nextState);
      },
      setLiveContent: (snapshot) => {
        setCardLiveContent(runtimeItemId(itemRef.current), snapshot);
      },
      getLiveContent: () => getCardLiveContent(runtimeItemId(itemRef.current)),
      setSelection: (selection) => {
        setCardSelection(runtimeItemId(itemRef.current), selection);
      },
      getSelection: () => getCardSelection(runtimeItemId(itemRef.current)),
      clearSelection: () => {
        clearCardSelection(runtimeItemId(itemRef.current));
      },
      setRefreshHandler: (handler) => {
        setCardRefreshHandler(runtimeItemId(itemRef.current), handler);
      },
      runRefresh: () => runCardRefresh(runtimeItemId(itemRef.current)),
      requestFeedRefresh: () => {
        requestCardFeedRefresh();
      },
      callTool: callManualTool,
      startToolCall: startManualToolCall,
      getToolJob: getManualToolJob,
      callToolAsync: callManualToolAsync,
      listTools: listManualTools,
      renderMarkdown: (markdown, options = {}) =>
        options.inline
          ? (marked.parseInline(markdown) as string)
          : (marked.parse(markdown) as string),
      copyText: copyTextToClipboard,
      getThemeName: () => document.documentElement.dataset.theme || "clay",
      getThemeValue: (tokenName) => {
        const normalized = tokenName.startsWith("--") ? tokenName : `--${tokenName}`;
        return getComputedStyle(document.documentElement).getPropertyValue(normalized).trim();
      },
    };
  }

  hostRef.current.surface = surface;
  hostRef.current.item = item;
  return hostRef.current;
}
