import { Edge, Node } from '@xyflow/react';
import { AppNodeData, AppNodeType, InputAsset } from './types/node';
import { GenerationType } from './controls/interaction-input/types';
import { sortInputAssetsByTypeOrder } from './utils';

type AudioModels = Record<string, { voices?: Array<{ id?: string; value?: string; gender?: string }> }>;

export function mapNodeTypeToTab(nodeType: string, nodeData?: Partial<AppNodeData>): GenerationType {
  switch (nodeType) {
    case 'IMAGE_GENERATOR':
    case 'IMAGE_EDITOR':
      return 'image';
    case 'VIDEO_GENERATOR':
      return 'video';
    case 'LYRICS_GENERATOR':
      return 'music';
    case 'AUDIO_GENERATOR':
      return nodeData?.generationType === 'music' ? 'music' : 'audio';
    default:
      return 'text';
  }
}

export function buildInputAssets(params: {
  isEditMode: boolean;
  selectedNodeId: string | null;
  edges: Edge[];
  nodes: Node[];
  audioModels: AudioModels;
}): InputAsset[] {
  const { isEditMode, selectedNodeId, edges, nodes, audioModels } = params;
  const assets: InputAsset[] = [];
  const typeCounters: Record<InputAsset['type'], number> = {
    image: 0,
    video: 0,
    audio: 0,
  };

  const getAudioGender = (data: AppNodeData) => {
    if (!data.model || !data.voice) return undefined;
    const voices = audioModels[data.model]?.voices;
    const match = voices?.find((voice) => (voice.value ?? voice.id) === data.voice);
    return match?.gender;
  };

  const pushAsset = (appNode: AppNodeType) => {
    const data = appNode.data as AppNodeData;
    const label = data.title;

    if (data.image) {
      const index = ++typeCounters.image;
      assets.push({
        id: appNode.id,
        type: 'image',
        src: data.image,
        label,
        logicalRole: `image_${index}`,
        mentionAlias: `图片${index}`,
      });
      return;
    }

    if (data.videoUri) {
      const index = ++typeCounters.video;
      assets.push({
        id: appNode.id,
        type: 'video',
        src: data.videoUri,
        label,
        logicalRole: `video_${index}`,
        mentionAlias: `视频${index}`,
      });
      return;
    }

    if (data.audioUri) {
      const index = ++typeCounters.audio;
      assets.push({
        id: appNode.id,
        type: 'audio',
        src: data.audioUri,
        gender: getAudioGender(data),
        label,
        logicalRole: `audio_${index}`,
        mentionAlias: `音频${index}`,
      });
    }
  };

  if (isEditMode && selectedNodeId) {
    const inputIds = edges.filter((edge) => edge.target === selectedNodeId).map((edge) => edge.source);
    const sortedInputNodes = inputIds
      .map((id) => nodes.find((node) => node.id === id))
      .filter((node): node is AppNodeType => !!node && node.type === 'appNode')
      .sort((a, b) => a.position.y - b.position.y);

    sortedInputNodes.forEach(pushAsset);
  } else {
    const selectedNodes = nodes
      .filter((node) => node.selected && node.type === 'appNode')
      .sort((a, b) => a.position.y - b.position.y) as AppNodeType[];

    selectedNodes.forEach(pushAsset);
  }

  return sortInputAssetsByTypeOrder(assets);
}
