import { type Edge, type Node, useNodesData, useStore } from '@xyflow/svelte';
import type { Parameter } from '#types';
import { getCurrentNodeId, getOptions } from '#components/utils/NodeUtils';
import { getStartNodeParameterLabel } from '#components/utils/startNodeParameterLabel';
import { nodeIcons } from '../../consts';
import {
  buildLoopReferenceParameters,
  buildLoopScopeParameters,
  isArrayDataType,
  projectParameterDataType,
} from '../../utils/loopScope';
import { filterRefOptionsByContentType } from './refOptionFilter';

const fillRefNodeIds = (
  refNodeIds: string[],
  currentNodeId: string,
  edges: Edge[],
) => {
  for (const edge of edges) {
    if (edge.target === currentNodeId && edge.source) {
      refNodeIds.push(edge.source);
      fillRefNodeIds(refNodeIds, edge.source, edges);
    }
  }
};

const getChildren = (
  params: any,
  parentId: string,
  nodeType: string,
  parentPathLabel = '',
  ancestorCollectionDepth = 0,
  parentIsCollection = false,
) => {
  if (!params || params.length === 0) return [];
  return params.map((param: any) => {
    const isCollection =
      isArrayDataType(param.dataType) &&
      param.children &&
      param.children.length > 0;
    const childBaseLabel = param.formLabel || param.displayName || param.name;
    const normalizedChildLabel = String(childBaseLabel || '').trim();
    const pathLabel = !parentPathLabel
      ? normalizedChildLabel
      : parentIsCollection
        ? `${parentPathLabel}.[].${normalizedChildLabel}`
        : `${parentPathLabel}.${normalizedChildLabel}`;
    const dataType = projectParameterDataType(
      param,
      ancestorCollectionDepth,
    );
    const nextCollectionDepth =
      ancestorCollectionDepth + (isCollection ? 1 : 0);
    return {
      label: pathLabel,
      dataType,
      contentType: param.contentType,
      value: parentId + '.' + param.name,
      selectable: true,
      nodeType: nodeType,
      displayLabel: pathLabel,
      pathLabel,
      itemTypeLabel:
        ancestorCollectionDepth > 0 ? '数组项字段' : undefined,
      isCollection,
      children: getChildren(
        param.children,
        parentId + '.' + param.name,
        nodeType,
        pathLabel,
        nextCollectionDepth,
        isCollection,
      ),
    };
  });
};

const nodeToOptions = (
  node: Node,
  currentNode: Node,
  nodes: Node[],
) => {
  const options = getOptions();
  const nodeType = node.type || '';

  let icon: string | undefined = nodeIcons[nodeType];
  if (!icon && options?.customNodes && options.customNodes[nodeType]) {
    icon = options.customNodes[nodeType].icon;
  }

  // 如果仍然获取不到，尝试使用 data.icon (作为回退)
  if (!icon && node.data && node.data.icon) {
    icon = node.data.icon as string;
  }

  const title = node.data.title;

  if (nodeType === 'startNode') {
    const parameters = node.data.parameters as Array<Parameter>;
    const children = [];
    if (parameters)
      for (const parameter of parameters) {
        const label = getStartNodeParameterLabel(parameter);
        children.push({
          label,
          dataType: projectParameterDataType(parameter),
          contentType: parameter.contentType,
          value: node.id + '.' + parameter.name,
          selectable: true,
          nodeType: nodeType,
        });
      }
    return {
      label: title,
      icon: icon,
      value: node.id,
      selectable: false,
      nodeType: nodeType,
      children,
    };
  } else if (nodeType === 'loopNode') {
    const referenceParameters = buildLoopReferenceParameters(
      node,
      currentNode,
      nodes,
    );
    if (!referenceParameters.length) {
      return undefined;
    }
    return {
      label: title,
      icon: icon,
      value: node.id,
      selectable: false,
      nodeType: nodeType,
      children: getChildren(
        referenceParameters,
        node.id,
        nodeType,
      ),
    };
  } else {
    const outputDefs = node.data.outputDefs;
    if (outputDefs) {
      return {
        label: title,
        icon: icon,
        value: node.id,
        selectable: false,
        nodeType: nodeType,
        children: getChildren(outputDefs, node.id, nodeType),
      };
    }
  }
};

export const useRefOptions: any = (
  useChildrenOnly: boolean | (() => boolean) = false,
  acceptedContentTypes: string[] | (() => string[]) = [],
  currentRef: string | (() => string) = '',
) => {
  const currentNodeId = getCurrentNodeId();
  const currentNode = useNodesData(currentNodeId);
  const { nodes, edges, nodeLookup } = $derived(useStore());
  const isChildrenOnly = () =>
    typeof useChildrenOnly === 'function'
      ? useChildrenOnly()
      : useChildrenOnly;
  const getAcceptedContentTypes = () =>
    typeof acceptedContentTypes === 'function'
      ? acceptedContentTypes()
      : acceptedContentTypes;
  const getCurrentRef = () =>
    typeof currentRef === 'function' ? currentRef() : currentRef;

  let selectItems = $derived.by(() => {
    const resultOptions = [];
    if (!currentNode.current) {
      return {
        items: [],
        selected: undefined,
      };
    }

    //通过 nodeLookup.get 才会得到有 parentId 的 node
    const cNode = nodeLookup.get(currentNodeId)!;

    if (isChildrenOnly()) {
      for (const node of nodes) {
        if (node.parentId === currentNode.current.id) {
          const nodeOptions = nodeToOptions(
            node,
            cNode,
            nodes,
          );
          nodeOptions && resultOptions.push(nodeOptions);
        }
      }
    } else {
      const refNodeIds: string[] = [];
      fillRefNodeIds(refNodeIds, currentNodeId, edges);

      for (const node of nodes) {
        const isScopedLoop =
          node.type === 'loopNode' &&
          buildLoopScopeParameters(node, cNode, nodes).length > 0;
        if (refNodeIds.includes(node.id) || isScopedLoop) {
          const nodeOptions = nodeToOptions(
            node,
            cNode,
            nodes,
          );
          nodeOptions && resultOptions.push(nodeOptions);
        }
      }
    }

    const items = filterRefOptionsByContentType(
      resultOptions,
      getAcceptedContentTypes(),
      getCurrentRef(),
    );
    const stack = [...items];
    let selected;
    const currentValue = getCurrentRef();
    // 单次深度优先扫描定位当前引用，避免为每个参数额外构建全量索引。
    while (stack.length > 0) {
      const item = stack.pop();
      if (item?.value === currentValue) {
        selected = item;
        break;
      }
      if (item?.children?.length) {
        stack.push(...item.children);
      }
    }
    return { items, selected };
  });

  return {
    get current() {
      return selectItems.items;
    },
    get selected() {
      return selectItems.selected;
    },
  };
};
