import { useRef, useEffect, useCallback } from 'react';
import { AppNodeData } from '../types/node';
import { GenerationSettings, GenerationType } from '../controls/interaction-input/types';
import { mapNodeTypeToTab } from '../interaction-input-helpers';

const DEBOUNCE_MS = 300;

export interface UseInteractionEditModeParams {
  isEditMode: boolean;
  selectedNodeId: string | null;
  selectedNodeData: AppNodeData | undefined;
  updateNodeData: (data: Partial<AppNodeData>) => void;
  inputText: string;
  settings: GenerationSettings;
  activeTab: GenerationType;
  setInputText: (v: string) => void;
  setSettings: (v: GenerationSettings | ((prev: GenerationSettings) => GenerationSettings)) => void;
  setActiveTab: (v: GenerationType) => void;
  setIsExpanded: (v: boolean) => void;
  defaultSettings: GenerationSettings;
}

/**
 * 封装底部输入栏「编辑态」逻辑：进入/退出时与节点数据同步、输入/设置回写节点。
 * 主组件只做组合与布局，编辑态同步细节集中在此便于单测与复用。
 */
export function useInteractionEditMode({
  isEditMode,
  selectedNodeId,
  selectedNodeData,
  updateNodeData,
  inputText,
  settings,
  activeTab,
  setInputText,
  setSettings,
  setActiveTab,
  setIsExpanded,
  defaultSettings,
}: UseInteractionEditModeParams) {
  const globalStateRef = useRef<{
    inputText: string;
    settings: GenerationSettings;
    activeTab: GenerationType;
  }>({ inputText: '', settings: defaultSettings, activeTab: 'text' });
  const prevEditNodeIdRef = useRef<string | null>(null);
  const promptSyncTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Enter/exit edit mode: sync node data to/from bottom bar
  useEffect(() => {
    if (isEditMode && selectedNodeData && selectedNodeId !== prevEditNodeIdRef.current) {
      if (!prevEditNodeIdRef.current) {
        globalStateRef.current = { inputText, settings, activeTab };
      }
      prevEditNodeIdRef.current = selectedNodeId;

      const tab = mapNodeTypeToTab(selectedNodeData.type, selectedNodeData);
      setActiveTab(tab);
      setInputText(selectedNodeData.prompt || selectedNodeData.userPrompt || '');

      const nodeSettings: GenerationSettings = {
        ...defaultSettings,
        model: selectedNodeData.model || '',
        resolution: selectedNodeData.resolution || defaultSettings.resolution,
        aspectRatio: selectedNodeData.aspectRatio || defaultSettings.aspectRatio,
        duration: selectedNodeData.duration || defaultSettings.duration,
        count:
          (tab === 'image' ? selectedNodeData.imageCount : selectedNodeData.videoCount) ?? 1,
        shotType: selectedNodeData.shotType,
        enableAudio: selectedNodeData.enableAudio,
        cameraControl: selectedNodeData.cameraControl,
        voice: selectedNodeData.voice as string | undefined,
        styleId: selectedNodeData.styleId,
        lyricsModel:
          selectedNodeData.type === 'LYRICS_GENERATOR'
            ? selectedNodeData.model || ''
            : settings.lyricsModel || '',
        musicModel:
          selectedNodeData.type === 'AUDIO_GENERATOR' && selectedNodeData.generationType === 'music'
            ? selectedNodeData.model || ''
            : settings.musicModel || '',
        musicTarget:
          selectedNodeData.type === 'LYRICS_GENERATOR'
            ? 'lyrics'
            : selectedNodeData.type === 'AUDIO_GENERATOR' && selectedNodeData.generationType === 'music'
              ? 'music'
              : (settings.musicTarget || 'music'),
        musicGenerateLyrics: selectedNodeData.type === 'LYRICS_GENERATOR',
        musicGenerateMusic:
          selectedNodeData.type === 'AUDIO_GENERATOR' && selectedNodeData.generationType === 'music',
      };
      setSettings(nodeSettings);
    } else if (!isEditMode && prevEditNodeIdRef.current) {
      prevEditNodeIdRef.current = null;
      setInputText(globalStateRef.current.inputText);
      setSettings(globalStateRef.current.settings);
      setActiveTab(globalStateRef.current.activeTab);
      setIsExpanded(false);
    }
  // Intentionally omit activeTab/inputText/settings to avoid re-syncing from node on every keystroke
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    isEditMode,
    selectedNodeId,
    selectedNodeData,
    defaultSettings,
    setInputText,
    setSettings,
    setActiveTab,
    setIsExpanded,
    settings.lyricsModel,
    settings.musicModel,
    settings.musicTarget,
  ]);

  const handleEditModeSettingsUpdate = useCallback(
    (newSettings: GenerationSettings) => {
      setSettings(newSettings);
      if (isEditMode && selectedNodeId) {
        const updates: Partial<AppNodeData> = {};
        if (newSettings.model !== settings.model) updates.model = newSettings.model;
        if (newSettings.resolution !== settings.resolution)
          updates.resolution = newSettings.resolution;
        if (newSettings.aspectRatio !== settings.aspectRatio)
          updates.aspectRatio = newSettings.aspectRatio;
        if (newSettings.duration !== settings.duration)
          updates.duration = newSettings.duration;
        if (newSettings.shotType !== settings.shotType) updates.shotType = newSettings.shotType;
        if (newSettings.enableAudio !== settings.enableAudio)
          updates.enableAudio = newSettings.enableAudio;
        if (newSettings.cameraControl !== settings.cameraControl)
          updates.cameraControl = newSettings.cameraControl;
        if (newSettings.voice !== settings.voice) updates.voice = newSettings.voice;
        if (newSettings.styleId !== settings.styleId) updates.styleId = newSettings.styleId;
        if (newSettings.count !== settings.count) {
          if (activeTab === 'image') updates.imageCount = newSettings.count;
          else if (activeTab === 'video') updates.videoCount = newSettings.count;
        }
        if (Object.keys(updates).length > 0) updateNodeData(updates);
      }
    },
    [
      isEditMode,
      selectedNodeId,
      settings,
      activeTab,
      updateNodeData,
      setSettings,
    ]
  );

  const effectiveSetSettings = isEditMode ? handleEditModeSettingsUpdate : setSettings;

  const handleInputChange = useCallback(
    (text: string) => {
      setInputText(text);
      if (isEditMode && selectedNodeId) {
        if (promptSyncTimerRef.current) clearTimeout(promptSyncTimerRef.current);
        promptSyncTimerRef.current = setTimeout(() => {
          const isPromptGen = selectedNodeData?.type === 'PROMPT_GENERATOR';
          updateNodeData(isPromptGen ? { userPrompt: text } : { prompt: text });
        }, DEBOUNCE_MS);
      }
    },
    [isEditMode, selectedNodeId, selectedNodeData, updateNodeData, setInputText]
  );

  const clearPromptSync = useCallback(() => {
    if (promptSyncTimerRef.current) {
      clearTimeout(promptSyncTimerRef.current);
      promptSyncTimerRef.current = null;
    }
  }, []);

  return {
    handleInputChange,
    handleEditModeSettingsUpdate,
    effectiveSetSettings,
    clearPromptSync,
  };
}
