"use client";

import type { ReactNode } from "react";
import { TreeShellRustDomShellHost } from "@/components/sidebar/tree-shell-dom-host";
import type { TreeShellPickerItem } from "@/components/sidebar/tree-shell-dom-model";
import {
  TreeShellIframeHost,
} from "@/components/sidebar/tree-shell-iframe-host";
import type { KernelFileTreeProjectionItem } from "@/lib/kernel-file-tree";
import type { PageTreeProjectionItem } from "@/lib/tree-projection";
import { cn } from "@/lib/utils";

export type TreeRendererFamily = "react" | "rust_family";

export type TreeShellHostMode = "page" | "filetree" | "picker";

const RUST_RENDERER_CONTRACT = "rust_renderer_input_v1";
const RUST_WASM_DOM_SHELL_HOST = "rust_wasm_dom_shell_host";
const RUST_LEGACY_IFRAME_HOST = "rust_runtime_artifact_host";

export type TreeShellPickerCommand = {
  kind: "next" | "previous" | "home" | "end" | "pick";
  seq: number;
};

export type FileTreeShellInternalDropPayload = {
  targetDocumentId: string | null;
  targetRowId: string | null;
  targetRowKind: string | null;
  targetAssetId: string | null;
  rowIds: string[];
  copy: boolean;
};

export type FileTreeShellExternalDropPayload = {
  targetDocumentId: string | null;
  targetRowId: string | null;
  targetRowKind: string | null;
  targetAssetId: string | null;
  files: FileList | File[];
};

type TreeShellHostProps = {
  mode: TreeShellHostMode;
  surfaceTestId: string;
  rendererFamily?: TreeRendererFamily;
  className?: string;
  treeShellEnabled?: boolean;
  fallbackImplementation?: string;
  workspaceId?: string | null;
  rootNodeId?: string | null;
  activeDocumentId?: string | null;
  focusedDocumentId?: string | null;
  activePickerItemKey?: string | null;
  allowRootPick?: boolean;
  excludeIds?: string[];
  pickerCommand?: TreeShellPickerCommand | null;
  pickerItems?: TreeShellPickerItem[];
  pageTreeItems?: PageTreeProjectionItem[];
  inlineFileTreeItems?: KernelFileTreeProjectionItem[];
  channel?: string;
  host?: string;
  onNavigate?: (documentId: string) => void;
  onPick?: (targetId: string | null) => void;
  onPickerFocusChange?: (payload: { itemKey: string | null; documentId: string | null }) => void;
  onPageContextMenu?: (payload: { documentId: string; x: number; y: number }) => void;
  onPageExpandChange?: (payload: { documentId: string | null; expanded: boolean }) => void;
  onPageFocusChange?: (payload: { documentId: string | null }) => void;
  onFileTreeContextMenu?: (payload: {
    documentId: string | null;
    assetId: string | null;
    rowId: string | null;
    rowKind: string | null;
    x: number;
    y: number;
  }) => void;
  onFileTreeSelectionChange?: (payload: {
    selectedRowIds: string[];
    anchorRowId: string | null;
    focusedRowId: string | null;
  }) => void;
  onInternalDrop?: (payload: FileTreeShellInternalDropPayload) => void;
  onDropFiles?: (payload: FileTreeShellExternalDropPayload) => void;
  onAssetOpen?: (payload: { assetId: string; documentId: string | null }) => void;
  onTreeMutation?: (payload: { type: string; documentId: string | null }) => void;
  children: ReactNode;
};

export function TreeShellHost({
  mode,
  surfaceTestId,
  rendererFamily = "react",
  className,
  treeShellEnabled = true,
  fallbackImplementation,
  workspaceId = null,
  rootNodeId = null,
  activeDocumentId = null,
  focusedDocumentId = null,
  activePickerItemKey = null,
  allowRootPick = false,
  excludeIds = [],
  pickerCommand = null,
  pickerItems,
  pageTreeItems,
  inlineFileTreeItems,
  channel,
  host,
  onNavigate,
  onPick,
  onPickerFocusChange,
  onPageContextMenu,
  onPageExpandChange,
  onPageFocusChange,
  onFileTreeContextMenu,
  onFileTreeSelectionChange,
  onInternalDrop,
  onDropFiles,
  onAssetOpen,
  onTreeMutation,
  children,
}: TreeShellHostProps) {
  const useRustHost = rendererFamily === "rust_family";
  const useDomHost = useRustHost && Boolean(workspaceId?.trim());
  const useLegacyIframeHost =
    useDomHost &&
    typeof process !== "undefined" &&
    process.env.NEXT_PUBLIC_TREE_SHELL_LEGACY_IFRAME_HOST === "1";
  const hostKind = rendererFamily === "rust_family" ? "rust_family" : "react";
  const rendererContract = useRustHost ? RUST_RENDERER_CONTRACT : undefined;
  const implementation = useLegacyIframeHost
    ? RUST_LEGACY_IFRAME_HOST
    : useDomHost
      ? RUST_WASM_DOM_SHELL_HOST
    : fallbackImplementation ??
      (rendererFamily === "rust_family" ? "react_fallback" : "react_primary");

  return (
    <div
      data-testid={surfaceTestId}
      data-shell-mode={mode}
      data-renderer-family={rendererFamily}
      data-tree-host-kind={hostKind}
      data-tree-host-implementation={implementation}
      data-tree-renderer-contract={rendererContract}
      data-page-tree-focused-id={mode === "page" ? (focusedDocumentId ?? "") : undefined}
      className={cn(className)}
    >
      {useRustHost ? (
        <div
          data-testid={`${surfaceTestId}-rust-host`}
          data-tree-host-mode={mode}
          data-tree-host-kind="rust_family"
          data-tree-host-implementation={implementation}
          data-tree-renderer-contract={rendererContract}
          className="contents"
        >
          {useDomHost && workspaceId ? (
            useLegacyIframeHost ? (
              <TreeShellIframeHost
                mode={mode}
                surfaceTestId={surfaceTestId}
                workspaceId={workspaceId}
                rootNodeId={rootNodeId}
                activeDocumentId={activeDocumentId}
                focusedDocumentId={focusedDocumentId}
                activePickerItemKey={activePickerItemKey}
                allowRootPick={allowRootPick}
                excludeIds={excludeIds}
                pickerCommand={pickerCommand}
                pickerItems={pickerItems}
                pageTreeItems={pageTreeItems}
                inlineFileTreeItems={inlineFileTreeItems}
                channel={channel}
                host={host}
                onNavigate={onNavigate}
                onPick={onPick}
                onPickerFocusChange={onPickerFocusChange}
                onPageContextMenu={onPageContextMenu}
                onPageExpandChange={onPageExpandChange}
                onPageFocusChange={onPageFocusChange}
                onFileTreeContextMenu={onFileTreeContextMenu}
                onFileTreeSelectionChange={onFileTreeSelectionChange}
                onInternalDrop={onInternalDrop}
                onDropFiles={onDropFiles}
                onAssetOpen={onAssetOpen}
                onTreeMutation={onTreeMutation}
              />
            ) : (
              <TreeShellRustDomShellHost
                mode={mode}
                surfaceTestId={surfaceTestId}
                workspaceId={workspaceId}
                rootNodeId={rootNodeId}
                activeDocumentId={activeDocumentId}
                focusedDocumentId={focusedDocumentId}
                activePickerItemKey={activePickerItemKey}
                allowRootPick={allowRootPick}
                excludeIds={excludeIds}
                pickerCommand={pickerCommand}
                pickerItems={pickerItems}
                pageTreeItems={pageTreeItems}
                inlineFileTreeItems={inlineFileTreeItems}
                channel={channel}
                host={host}
                onNavigate={onNavigate}
                onPick={onPick}
                onPickerFocusChange={onPickerFocusChange}
                onPageContextMenu={onPageContextMenu}
                onPageExpandChange={onPageExpandChange}
                onPageFocusChange={onPageFocusChange}
                onFileTreeContextMenu={onFileTreeContextMenu}
                onFileTreeSelectionChange={onFileTreeSelectionChange}
                onInternalDrop={onInternalDrop}
                onDropFiles={onDropFiles}
                onAssetOpen={onAssetOpen}
                onTreeMutation={onTreeMutation}
              >
                {children}
              </TreeShellRustDomShellHost>
            )
          ) : (
            children
          )}
        </div>
      ) : (
        children
      )}
    </div>
  );
}
