import React, { useState, useEffect, useMemo } from 'react';
import {
  Box,
  Typography,
  Button,
  TextField,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
  List,
  ListItem,
  ListItemText,
  ListItemSecondaryAction,
  IconButton,
  Chip,
  CircularProgress,
  Alert,
  Snackbar,
  useTheme,
  Tooltip,
  Tabs,
  Tab,
  FormControl,
  Select,
  MenuItem,
} from '@mui/material';
import {
  Add as AddIcon,
  Save as SaveIcon,
  Delete as DeleteIcon,
  Edit as EditIcon,
  ContentCopy as CopyIcon,
  Refresh as RefreshIcon,
  CheckCircle as CheckIcon,
  Error as ErrorIcon,
  AccountTree as TreeIcon,
  ShowChart as ChartIcon,
  TrendingUp,
  TrendingDown,
  FileDownload as ExportIcon,
  FileUpload as ImportIcon,
  CloudDownload as ExportAllIcon,
  CloudUpload as ImportAllIcon,
  NotificationsActive,
  NotificationsOff,
} from '@mui/icons-material';
import { DndContext, DragEndEvent, DragStartEvent, DragOverlay, PointerSensor, useSensor, useSensors, defaultDropAnimationSideEffects } from '@dnd-kit/core';
import NodePalette from '../components/strategy-tree/NodePalette';
import StrategyTreeBuilder from '../components/strategy-tree/StrategyTreeBuilder';
import {
  LogicNode,
  StrategyDSLDto,
  getDSLStrategy,
  createDSLStrategy,
  updateDSLStrategy,
  deleteDSLStrategy,
  duplicateDSLStrategy,
  nodeToNaturalLanguage,
  validateStrategyTree,
  ValidationResult,
  generateNodeId,
} from '../services/strategyDSLApi';
import { useIndicatorVisibility } from '../contexts/IndicatorVisibilityContext';
import { StrategyTemplate } from '../components/strategy-tree/strategyTemplates';
import {
  getAllAlertStrategies,
  addAlertStrategy,
  deleteAlertStrategy,
  AlertStrategyDto,
} from '../services/alertStrategyApi';

// ============================================================
// StrategyTreeBuilderPage 메인 컴포넌트
// ============================================================

const StrategyTreeBuilderPage: React.FC = () => {
  const theme = useTheme();
  const { settings: visibilitySettings } = useIndicatorVisibility();

  // 상태 관리
  const [strategies, setStrategies] = useState<StrategyDSLDto[]>([]);
  const [selectedStrategy, setSelectedStrategy] = useState<StrategyDSLDto | null>(null);
  const [buyCondition, setBuyCondition] = useState<LogicNode | null>(null);
  const [sellCondition, setSellCondition] = useState<LogicNode | null>(null);
  const [currentTab, setCurrentTab] = useState<'buy' | 'sell'>('buy');
  const [rightPanelTab, setRightPanelTab] = useState<'list' | 'preview' | 'alerts'>('list');
  const [strategyName, setStrategyName] = useState('');
  const [strategyDescription, setStrategyDescription] = useState('');
  const [isLoading, setIsLoading] = useState(false);
  const [isSaving, setIsSaving] = useState(false);
  
  // 알림 전략 상태
  const [alertStrategies, setAlertStrategies] = useState<AlertStrategyDto[]>([]);
  const [alertLoading, setAlertLoading] = useState(false);
  const [alertSortOrder, setAlertSortOrder] = useState<'name-asc' | 'name-desc' | 'date-asc' | 'date-desc'>('name-asc');
  const [strategySortOrder, setStrategySortOrder] = useState<'name-asc' | 'name-desc' | 'date-asc' | 'date-desc'>('name-asc');

  // 다이얼로그 상태
  const [saveDialogOpen, setSaveDialogOpen] = useState(false);
  const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
  const [deleteTargetId, setDeleteTargetId] = useState<number | null>(null);

  // 스낵바 상태
  const [snackbarOpen, setSnackbarOpen] = useState(false);
  const [snackbarMessage, setSnackbarMessage] = useState('');
  const [snackbarSeverity, setSnackbarSeverity] = useState<'success' | 'error'>('success');

  // 드래그 중인 항목 상태
  const [activeDragItem, setActiveDragItem] = useState<any>(null);
  const [dropSuccess, setDropSuccess] = useState(false);

  // 검증 결과 상태
  const [buyValidation, setBuyValidation] = useState<ValidationResult | null>(null);
  const [sellValidation, setSellValidation] = useState<ValidationResult | null>(null);

  // 드래그 센서 설정
  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 8, // 8px 이동 후 드래그 시작
      },
    })
  );

  // 알림목록 정렬 (이름/날짜 × 오름차순/내림차순)
  const sortedAlertStrategies = useMemo(() => {
    const sorted = [...alertStrategies];
    const getDisplayName = (a: AlertStrategyDto) => {
      const strategy = strategies.find(s => s.id === a.strategyRuleId);
      return a.strategyRuleName || strategy?.name || '알 수 없는 전략';
    };
    const getSortDate = (a: AlertStrategyDto) => {
      const dateStr = a.createdAt || a.updatedAt || '';
      return dateStr ? new Date(dateStr).getTime() : 0;
    };
    sorted.sort((a, b) => {
      switch (alertSortOrder) {
        case 'name-asc':
          return getDisplayName(a).localeCompare(getDisplayName(b), 'ko');
        case 'name-desc':
          return getDisplayName(b).localeCompare(getDisplayName(a), 'ko');
        case 'date-asc':
          return getSortDate(a) - getSortDate(b);
        case 'date-desc':
          return getSortDate(b) - getSortDate(a);
        default:
          return 0;
      }
    });
    return sorted;
  }, [alertStrategies, strategies, alertSortOrder]);

  // ✅ MA 필드를 동적 라벨로 변환
  const convertMAFieldToLabel = (field: string | undefined): string => {
    if (!field) return '';
    if (field === 'CLOSE_PRICE') return '종가';
    if (field === 'NONE') return '';
    
    // MA5, MA10, MA20 등 파싱
    const match = field.match(/^MA(\d+)$/);
    if (!match) return field;
    
    const period = parseInt(match[1]);
    const enabledMAs = (visibilitySettings.maLines || []).filter(ma => ma.enabled);
    const allMAs = visibilitySettings.maLines || [];
    
    // 1단계: enabled된 MA 중에서 찾기
    let maIndex = enabledMAs.findIndex(ma => ma.period === period);
    if (maIndex >= 0) {
      return `MA${maIndex + 1}(${period}일)`;
    }
    
    // 2단계: 전체 MA 목록에서 찾기 (disabled 포함)
    const allIndex = allMAs.findIndex(ma => ma.period === period);
    if (allIndex >= 0) {
      return `MA${allIndex + 1}(${period}일)`;
    }
    
    // 3단계: 가장 가까운 enabled MA 찾기
    if (enabledMAs.length > 0) {
      const closest = enabledMAs.reduce((prev, curr) => {
        return Math.abs(curr.period - period) < Math.abs(prev.period - period) ? curr : prev;
      });
      const closestIndex = enabledMAs.findIndex(ma => ma.period === closest.period);
      return `MA${closestIndex + 1}(${closest.period}일)`;
    }
    
    // 4단계: 못 찾으면 기간만 표시
    return `${period}일`;
  };

  // ✅ 전략 이름을 동적으로 생성 (MA 조건인 경우)
  const generateDynamicStrategyName = (condition: LogicNode | null | undefined): string => {
    if (!condition || condition.type !== 'CONDITION' || !condition.condition) {
      return '';
    }
    
    const cond = condition.condition;
    
    // MA 조건인 경우에만 동적 생성
    if (cond.indicatorType === 'MA') {
      const leftLabel = convertMAFieldToLabel(cond.leftField);
      const rightLabel = convertMAFieldToLabel(cond.rightField);
      
      const conditionLabel = cond.conditionType === 'CROSS_UP' ? '상향돌파' :
                             cond.conditionType === 'CROSS_DOWN' ? '하향돌파' :
                             cond.conditionType === 'GT' ? '>' :
                             cond.conditionType === 'LT' ? '<' : cond.conditionType;
      
      if (rightLabel) {
        return `${leftLabel} ${conditionLabel} ${rightLabel}`;
      }
      return `${leftLabel} ${conditionLabel}`;
    }
    
    return '';
  };

  // 전략목록 정렬 (이름/날짜 × 오름차순/내림차순)
  const sortedStrategies = useMemo(() => {
    const sorted = [...strategies];
    const getDisplayName = (s: StrategyDSLDto) => {
      try {
        const dslData = JSON.parse(s.dslJson || '{}');
        const buyConditionNode = dslData.buyCondition;
        const dynamicName = generateDynamicStrategyName(buyConditionNode);
        return dynamicName || s.name || '';
      } catch {
        return s.name || '';
      }
    };
    const getSortDate = (s: StrategyDSLDto) => {
      const dateStr = s.createdAt || s.updatedAt || '';
      return dateStr ? new Date(dateStr).getTime() : 0;
    };
    sorted.sort((a, b) => {
      switch (strategySortOrder) {
        case 'name-asc':
          return getDisplayName(a).localeCompare(getDisplayName(b), 'ko');
        case 'name-desc':
          return getDisplayName(b).localeCompare(getDisplayName(a), 'ko');
        case 'date-asc':
          return getSortDate(a) - getSortDate(b);
        case 'date-desc':
          return getSortDate(b) - getSortDate(a);
        default:
          return 0;
      }
    });
    return sorted;
  }, [strategies, strategySortOrder]);

  // LogicNode를 논리 수식으로 변환 (괄호 포함)
  const nodeToLogicFormula = (node: LogicNode): string => {
    if (!node) return '';

    if (node.type === 'CONDITION' && node.condition) {
      // 조건 노드: 자연어 그대로 반환
      const naturalText = nodeToNaturalLanguage(node);
      return `(${naturalText})`;
    }

    if (node.type === 'AND') {
      // AND 노드: 모든 자식을 AND로 연결
      if (!node.children || node.children.length === 0) {
        return '(빈 AND 그룹)';
      }
      const childFormulas = node.children.map(child => nodeToLogicFormula(child));
      return `(${childFormulas.join(' AND ')})`;
    }

    if (node.type === 'OR') {
      // OR 노드: 모든 자식을 OR로 연결
      if (!node.children || node.children.length === 0) {
        return '(빈 OR 그룹)';
      }
      const childFormulas = node.children.map(child => nodeToLogicFormula(child));
      return `(${childFormulas.join(' OR ')})`;
    }

    if (node.type === 'NOT') {
      // NOT 노드: 자식 하나를 NOT으로 반전
      if (!node.children || node.children.length === 0) {
        return '(빈 NOT 그룹)';
      }
      const childFormula = nodeToLogicFormula(node.children[0]);
      return `NOT ${childFormula}`;
    }

    return '(알 수 없는 노드)';
  };

  // 현재 탭의 조건 가져오기
  const getCurrentRootNode = () => {
    return currentTab === 'buy' ? buyCondition : sellCondition;
  };

  // 현재 탭의 조건 설정
  const setCurrentRootNode = (node: LogicNode | null) => {
    if (currentTab === 'buy') {
      setBuyCondition(node);
    } else {
      setSellCondition(node);
    }
  };

  // ============================================================
  // 초기 로드
  // ============================================================

  useEffect(() => {
    loadStrategies();
    loadAlertStrategies();
    
    // 페이지가 다시 보일 때마다 알림 전략 목록 새로고침
    const handleVisibilityChange = () => {
      if (!document.hidden) {
        loadAlertStrategies();
      }
    };
    
    // 다른 화면에서 알림 전략이 변경되었을 때 새로고침
    const handleAlertStrategyChanged = () => {
      console.log('[Strategy Tree] 알림 전략 변경 이벤트 수신, 목록 새로고침');
      loadAlertStrategies();
    };
    
    document.addEventListener('visibilitychange', handleVisibilityChange);
    window.addEventListener('alertStrategyChanged', handleAlertStrategyChanged);
    
    return () => {
      document.removeEventListener('visibilitychange', handleVisibilityChange);
      window.removeEventListener('alertStrategyChanged', handleAlertStrategyChanged);
    };
  }, []);

  // 매수 조건 검증
  useEffect(() => {
    if (buyCondition) {
      const result = validateStrategyTree(buyCondition);
      setBuyValidation(result);
    } else {
      setBuyValidation(null);
    }
  }, [buyCondition]);

  // 매도 조건 검증
  useEffect(() => {
    if (sellCondition) {
      const result = validateStrategyTree(sellCondition);
      setSellValidation(result);
    } else {
      setSellValidation(null);
    }
  }, [sellCondition]);

  /**
   * 전략 목록 로드
   */
  const loadStrategies = async () => {
    setIsLoading(true);
    try {
      // 통합 API 사용: 모든 전략을 불러와서 표시
      const { getApiBaseUrl } = await import('../services/apiConfig');
      const apiBase = getApiBaseUrl();
      const response = await fetch(`${apiBase}/strategy-rules`);
      if (!response.ok) throw new Error('전략 목록 조회 실패');
      
      const allStrategies = await response.json();
      
      // StrategyRuleDto → StrategyDSLDto 변환
      const convertedStrategies: StrategyDSLDto[] = allStrategies.map((rule: any) => ({
        id: rule.id,
        name: rule.name,
        description: rule.description,
        strategyType: rule.strategyType || 'LEGACY',
        createdByUi: rule.createdByUi || 'FORM',
        enabled: rule.enabled,
        dslJson: rule.dslJson || null,
        useFsm: rule.useFsm || false,
        signalType: rule.signalType,
        trendType: rule.trendType,
      }));
      
      setStrategies(convertedStrategies);
    } catch (error) {
      showSnackbar('전략 목록 로드 실패', 'error');
      console.error('전략 로드 실패:', error);
    } finally {
      setIsLoading(false);
    }
  };

  // 알림 전략 목록 로드
  const loadAlertStrategies = async () => {
    console.log('[Strategy Tree] 알림 전략 목록 로드 시작');
    try {
      setAlertLoading(true);
      const alertList = await getAllAlertStrategies();
      console.log('[Strategy Tree] 알림 전략 목록 로드 완료:', {
        count: alertList.length,
        strategies: alertList.map(a => ({ id: a.id, strategyRuleId: a.strategyRuleId, name: a.strategyRuleName }))
      });
      setAlertStrategies(alertList);
    } catch (err) {
      console.error('[Strategy Tree] 알림 전략 목록 로드 실패:', err);
    } finally {
      setAlertLoading(false);
    }
  };

  /**
   * 전략 선택
   */
  const handleSelectStrategy = async (strategy: StrategyDSLDto) => {
    try {
      // LEGACY 전략은 편집 불가 안내
      if (strategy.strategyType === 'LEGACY' || strategy.createdByUi === 'FORM') {
        showSnackbar('이 전략은 "전략(기존)" 화면에서 편집할 수 있습니다', 'error');
        setSelectedStrategy(null);
        setBuyCondition(null);
        setSellCondition(null);
        return;
      }
      
      const fullStrategy = await getDSLStrategy(strategy.id!);
      setSelectedStrategy(fullStrategy);
      setStrategyName(fullStrategy.name);
      setStrategyDescription(fullStrategy.description || '');
      
      // DSL JSON 파싱 - 매수/매도 조건 분리
      if (fullStrategy.dslJson) {
        const parsed = JSON.parse(fullStrategy.dslJson);
        
        // 새 형식: { buyCondition, sellCondition }
        if (parsed.buyCondition !== undefined || parsed.sellCondition !== undefined) {
          setBuyCondition(parsed.buyCondition || null);
          setSellCondition(parsed.sellCondition || null);
        } else {
          // 구 형식: 단일 LogicNode (매수 조건으로 간주)
          setBuyCondition(parsed);
          setSellCondition(null);
        }
      } else {
        setBuyCondition(null);
        setSellCondition(null);
      }
    } catch (error) {
      showSnackbar('전략 로드 실패', 'error');
      console.error('전략 로드 실패:', error);
    }
  };

  /**
   * 새 전략 생성
   */
  const handleNewStrategy = () => {
    setSelectedStrategy(null);
    setBuyCondition(null);
    setSellCondition(null);
    setCurrentTab('buy');
    setStrategyName('');
    setStrategyDescription('');
  };

  /**
   * 저장 다이얼로그 열기
   */
  const handleOpenSaveDialog = () => {
    if (!buyCondition && !sellCondition) {
      showSnackbar('매수 또는 매도 조건을 최소 1개 이상 추가해주세요', 'error');
      return;
    }
    setSaveDialogOpen(true);
  };

  /**
   * 전략 저장
   */
  const handleSaveStrategy = async () => {
    if ((!buyCondition && !sellCondition) || !strategyName.trim()) {
      showSnackbar('전략 이름을 입력해주세요', 'error');
      return;
    }

    setIsSaving(true);
    try {
      // 매수/매도 조건을 하나의 객체로 묶어서 저장
      const dslJson = JSON.stringify({
        buyCondition: buyCondition,
        sellCondition: sellCondition,
      });

      if (selectedStrategy && selectedStrategy.id) {
        // 기존 전략 수정
        await updateDSLStrategy(selectedStrategy.id, {
          name: strategyName,
          description: strategyDescription,
          dslJson,
          enabled: selectedStrategy.enabled,
          useFsm: selectedStrategy.useFsm,
        });
        showSnackbar('전략이 수정되었습니다', 'success');
      } else {
        // 새 전략 생성
        await createDSLStrategy({
          name: strategyName,
          description: strategyDescription,
          dslJson,
          enabled: true,
          useFsm: false,
        });
        showSnackbar('전략이 생성되었습니다', 'success');
      }

      setSaveDialogOpen(false);
      loadStrategies();
    } catch (error) {
      showSnackbar('저장 실패', 'error');
      console.error('저장 실패:', error);
    } finally {
      setIsSaving(false);
    }
  };

  /**
   * 전략 삭제
   */
  const handleDeleteStrategy = async (id: number) => {
    try {
      await deleteDSLStrategy(id);
      showSnackbar('전략이 삭제되었습니다', 'success');
      
      if (selectedStrategy && selectedStrategy.id === id) {
        handleNewStrategy();
      }
      
      loadStrategies();
      setDeleteDialogOpen(false);
    } catch (error) {
      showSnackbar('삭제 실패', 'error');
      console.error('삭제 실패:', error);
    }
  };

  /**
   * 전략 복제
   */
  const handleDuplicateStrategy = async (id: number, name: string) => {
    try {
      const newName = prompt('새 전략 이름:', `${name} (복사본)`);
      if (!newName) return;

      await duplicateDSLStrategy(id, newName);
      showSnackbar('전략이 복제되었습니다', 'success');
      loadStrategies();
    } catch (error) {
      showSnackbar('복제 실패', 'error');
      console.error('복제 실패:', error);
    }
  };

  // 알림 전략 토글
  const handleToggleAlert = async (strategyRuleId: number, event: React.MouseEvent) => {
    event.stopPropagation(); // 전략 선택 이벤트 방지
    
    console.log('[Strategy Tree] 알림 토글 시작:', {
      strategyRuleId,
      currentAlertStrategies: alertStrategies.map(a => ({ id: a.id, strategyRuleId: a.strategyRuleId }))
    });
    
    try {
      setAlertLoading(true);
      
      // 현재 알림 전략 목록에서 해당 전략이 있는지 확인
      const existingAlert = alertStrategies.find(a => a.strategyRuleId === strategyRuleId);
      console.log('[Strategy Tree] 기존 알림 전략 확인:', existingAlert ? `존재함 (ID: ${existingAlert.id})` : '없음');
      
      if (existingAlert) {
        // 이미 추가되어 있으면 삭제
        console.log('[Strategy Tree] 알림 전략 삭제 시작:', { alertId: existingAlert.id, strategyRuleId });
        await deleteAlertStrategy(existingAlert.id!);
        console.log('[Strategy Tree] 알림 전략 삭제 완료, 목록 새로고침 시작');
        await loadAlertStrategies();
        console.log('[Strategy Tree] 알림 전략 삭제 및 새로고침 완료');
        showSnackbar('알림 전략이 해제되었습니다', 'success');
        
        // 다른 화면에 알림 상태 변경 알림
        window.dispatchEvent(new CustomEvent('alertStrategyChanged'));
      } else {
        // 추가되어 있지 않으면 추가
        console.log('[Strategy Tree] 알림 전략 추가 시작:', strategyRuleId);
        const addedStrategy = await addAlertStrategy(strategyRuleId);
        console.log('[Strategy Tree] 알림 전략 추가 완료:', addedStrategy);
        console.log('[Strategy Tree] 알림 전략 목록 새로고침 시작');
        await loadAlertStrategies();
        console.log('[Strategy Tree] 알림 전략 추가 및 새로고침 완료');
        showSnackbar('알림 전략이 추가되었습니다', 'success');
        
        // 다른 화면에 알림 상태 변경 알림
        window.dispatchEvent(new CustomEvent('alertStrategyChanged'));
      }
    } catch (err: any) {
      console.error('[Strategy Tree] 알림 전략 토글 실패:', err);
      console.error('[Strategy Tree] 에러 상세:', {
        message: err.message,
        response: err.response?.data,
        status: err.response?.status
      });
      const errorMessage = err.response?.data?.message || err.message || '알림 전략 토글에 실패했습니다.';
      showSnackbar(errorMessage, 'error');
    } finally {
      setAlertLoading(false);
    }
  };


  /**
   * 전략을 JSON 파일로 Export
   */
  const handleExportStrategy = () => {
    if (!buyCondition && !sellCondition) {
      showSnackbar('내보낼 전략 조건이 없습니다', 'error');
      return;
    }

    try {
      // Export할 데이터 구성
      const exportData = {
        version: '1.0',
        name: strategyName || '새 전략',
        description: strategyDescription || '',
        buyCondition: buyCondition,
        sellCondition: sellCondition,
        exportedAt: new Date().toISOString(),
      };

      // JSON 문자열로 변환
      const jsonString = JSON.stringify(exportData, null, 2);
      const blob = new Blob([jsonString], { type: 'application/json' });
      
      // 다운로드 링크 생성
      const url = URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;
      
      // 파일명: 전략명-날짜.json
      const fileName = `${(strategyName || '전략').replace(/[^a-zA-Z0-9가-힣_-]/g, '_')}_${new Date().toISOString().split('T')[0]}.json`;
      link.download = fileName;
      
      // 다운로드 실행
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      URL.revokeObjectURL(url);
      
      showSnackbar('전략이 JSON 파일로 내보내졌습니다', 'success');
    } catch (error) {
      showSnackbar('내보내기 실패', 'error');
      console.error('Export 실패:', error);
    }
  };

  /**
   * JSON 파일에서 전략을 Import
   */
  const handleImportStrategy = () => {
    try {
      // 파일 선택 input 생성
      const input = document.createElement('input');
      input.type = 'file';
      input.accept = '.json';
      
      input.onchange = async (e: Event) => {
        const target = e.target as HTMLInputElement;
        const file = target.files?.[0];
        
        if (!file) return;
        
        try {
          const text = await file.text();
          const importedData = JSON.parse(text);
          
          // 유효성 검사
          if (!importedData.buyCondition && !importedData.sellCondition) {
            showSnackbar('유효하지 않은 전략 파일입니다', 'error');
            return;
          }
          
          // 전략 로드
          setBuyCondition(importedData.buyCondition || null);
          setSellCondition(importedData.sellCondition || null);
          setStrategyName(importedData.name || '가져온 전략');
          setStrategyDescription(importedData.description || '');
          setSelectedStrategy(null); // 새 전략으로 취급
          
          showSnackbar('전략이 가져와졌습니다', 'success');
          setRightPanelTab('preview'); // 상세보기로 전환
        } catch (error) {
          showSnackbar('파일 읽기 실패', 'error');
          console.error('Import 실패:', error);
        }
      };
      
      // 파일 선택 대화상자 열기
      input.click();
    } catch (error) {
      showSnackbar('가져오기 실패', 'error');
      console.error('Import 실패:', error);
    }
  };

  /**
   * 모든 전략을 JSON 파일로 일괄 Export
   */
  const handleExportAllStrategies = async () => {
    if (strategies.length === 0) {
      showSnackbar('내보낼 전략이 없습니다', 'error');
      return;
    }

    try {
      setIsLoading(true);
      
      // 모든 전략의 상세 정보를 가져오기
      const detailedStrategies = await Promise.all(
        strategies.map(async (strategy) => {
          try {
            // DSL 전략만 내보내기 (LEGACY 전략은 제외)
            if (strategy.strategyType !== 'DSL' && strategy.createdByUi === 'FORM') {
              return null;
            }
            
            const fullStrategy = await getDSLStrategy(strategy.id!);
            const dslData = fullStrategy.dslJson ? JSON.parse(fullStrategy.dslJson) : {};
            
            return {
              name: fullStrategy.name,
              description: fullStrategy.description || '',
              strategyType: fullStrategy.strategyType,
              createdByUi: fullStrategy.createdByUi,
              enabled: fullStrategy.enabled,
              useFsm: fullStrategy.useFsm,
              buyCondition: dslData.buyCondition || null,
              sellCondition: dslData.sellCondition || null,
            };
          } catch (error) {
            console.error(`전략 ${strategy.id} 로드 실패:`, error);
            return null;
          }
        })
      );

      // null 제거 (로드 실패한 전략)
      const validStrategies = detailedStrategies.filter(s => s !== null);

      if (validStrategies.length === 0) {
        showSnackbar('내보낼 수 있는 전략이 없습니다', 'error');
        return;
      }

      // Export할 데이터 구성
      const exportData = {
        version: '1.0',
        exportedAt: new Date().toISOString(),
        totalCount: validStrategies.length,
        strategies: validStrategies,
      };

      // JSON 문자열로 변환
      const jsonString = JSON.stringify(exportData, null, 2);
      const blob = new Blob([jsonString], { type: 'application/json' });
      
      // 다운로드 링크 생성
      const url = URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;
      
      // 파일명: 전략목록-날짜.json
      const fileName = `전략목록_${new Date().toISOString().split('T')[0]}.json`;
      link.download = fileName;
      
      // 다운로드 실행
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      URL.revokeObjectURL(url);
      
      showSnackbar(`${validStrategies.length}개 전략이 내보내졌습니다`, 'success');
    } catch (error) {
      showSnackbar('전체 내보내기 실패', 'error');
      console.error('Export All 실패:', error);
    } finally {
      setIsLoading(false);
    }
  };

  /**
   * JSON 파일에서 여러 전략을 일괄 Import
   */
  const handleImportAllStrategies = () => {
    try {
      // 파일 선택 input 생성
      const input = document.createElement('input');
      input.type = 'file';
      input.accept = '.json';
      
      input.onchange = async (e: Event) => {
        const target = e.target as HTMLInputElement;
        const file = target.files?.[0];
        
        if (!file) return;
        
        try {
          setIsLoading(true);
          const text = await file.text();
          const importedData = JSON.parse(text);
          
          // 유효성 검사: 배열 형식 확인
          if (!importedData.strategies || !Array.isArray(importedData.strategies)) {
            showSnackbar('유효하지 않은 전략 목록 파일입니다', 'error');
            return;
          }
          
          const strategies = importedData.strategies;
          
          if (strategies.length === 0) {
            showSnackbar('가져올 전략이 없습니다', 'error');
            return;
          }
          
          // 각 전략을 DB에 저장
          let successCount = 0;
          let failCount = 0;
          
          for (const strategy of strategies) {
            try {
              // 매수/매도 조건을 DSL JSON으로 변환
              const dslJson = JSON.stringify({
                buyCondition: strategy.buyCondition,
                sellCondition: strategy.sellCondition,
              });
              
              // 전략 생성
              await createDSLStrategy({
                name: strategy.name,
                description: strategy.description || '',
                dslJson,
                enabled: strategy.enabled !== undefined ? strategy.enabled : true,
                useFsm: strategy.useFsm || false,
              });
              
              successCount++;
            } catch (error) {
              console.error(`전략 "${strategy.name}" 저장 실패:`, error);
              failCount++;
            }
          }
          
          // 결과 표시
          if (successCount > 0) {
            showSnackbar(`${successCount}개 전략이 가져와졌습니다${failCount > 0 ? ` (실패: ${failCount}개)` : ''}`, 'success');
            loadStrategies();
          } else {
            showSnackbar('모든 전략 가져오기 실패', 'error');
          }
        } catch (error) {
          showSnackbar('파일 읽기 실패', 'error');
          console.error('Import All 실패:', error);
        } finally {
          setIsLoading(false);
        }
      };
      
      // 파일 선택 대화상자 열기
      input.click();
    } catch (error) {
      showSnackbar('전체 가져오기 실패', 'error');
      console.error('Import All 실패:', error);
    }
  };

  /**
   * 스낵바 표시
   */
  const showSnackbar = (message: string, severity: 'success' | 'error') => {
    setSnackbarMessage(message);
    setSnackbarSeverity(severity);
    setSnackbarOpen(true);
  };

  /**
   * 드래그 시작 핸들러
   */
  const handleDragStart = (event: DragStartEvent) => {
    const { active } = event;
    setActiveDragItem(active.data.current);
    setDropSuccess(false);
  };

  /**
   * 드래그 종료 핸들러 - NodePalette에서 StrategyTreeBuilder로 드래그
   */
  const handleDragEnd = (event: DragEndEvent) => {
    // StrategyTreeBuilder가 이 이벤트를 처리하도록 전달
    // 실제 로직은 StrategyTreeBuilder 내부에서 처리됨
    
    // 드롭 성공하지 않은 경우에만 원래 자리로 돌아가는 애니메이션 적용
    setTimeout(() => {
      setActiveDragItem(null);
      setDropSuccess(false);
    }, dropSuccess ? 0 : 250);
  };

  /**
   * 드롭 성공 핸들러
   */
  const handleDropSuccess = () => {
    setDropSuccess(true);
  };

  /**
   * 템플릿 선택 핸들러
   */
  const handleTemplateSelect = (template: StrategyTemplate) => {
    console.log('🎨 템플릿 선택:', template.name, template.signal);
    
    // 템플릿의 condition을 복사하고 새 ID 생성
    // metadata에 템플릿 정보를 JSON으로 저장
    const templateMetadata = JSON.stringify({
      templateId: template.id,
      templateName: template.name,
      templateSignal: template.signal,
    });
    
    const newNode: LogicNode = {
      ...template.condition,
      id: generateNodeId(),
      metadata: templateMetadata,
    };
    
    // 매수/매도 시그널에 따라 해당 탭에 추가
    if (template.signal === 'buy') {
      setBuyCondition(newNode);
      setCurrentTab('buy');
      setRightPanelTab('preview'); // 우측 패널을 상세보기로 전환
      showSnackbar(`매수 조건에 "${template.name}" 템플릿이 추가되었습니다`, 'success');
    } else {
      setSellCondition(newNode);
      setCurrentTab('sell');
      setRightPanelTab('preview'); // 우측 패널을 상세보기로 전환
      showSnackbar(`매도 조건에 "${template.name}" 템플릿이 추가되었습니다`, 'success');
    }
  };

  // ============================================================
  // 드롭 애니메이션 설정
  // ============================================================

  const dropAnimation = dropSuccess
    ? {
        duration: 0,
        sideEffects: defaultDropAnimationSideEffects({
          styles: {
            active: {
              opacity: '0',
            },
          },
        }),
      }
    : {
        duration: 250,
        sideEffects: defaultDropAnimationSideEffects({
          styles: {
            active: {
              opacity: '0.5',
            },
          },
        }),
      };

  // ============================================================
  // 렌더링
  // ============================================================

  return (
    <DndContext sensors={sensors} onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
      <Box sx={{
        display: 'grid',
        gridTemplateColumns: '360px 1fr 360px',
        height: 'calc(100vh - 64px)',
        bgcolor: theme.palette.background.default,
        overflow: 'hidden',
        position: 'relative',
      }}>
        {/* 왼쪽 패널: 전략 구성요소 */}
        <Box sx={{
          bgcolor: theme.palette.background.paper,
          borderRight: `1px solid ${theme.palette.divider}`,
          display: 'flex',
          flexDirection: 'column',
          overflow: 'auto',
        }}>
          <NodePalette 
            disabled={false} 
            onTemplateSelect={handleTemplateSelect}
          />
        </Box>

        {/* 중앙: 편집기 */}
        <Box sx={{ 
          display: 'flex',
          flexDirection: 'column',
          bgcolor: theme.palette.background.paper,
          overflow: 'hidden',
          borderLeft: `1px solid ${theme.palette.divider}`,
          borderRight: `1px solid ${theme.palette.divider}`,
        }}>
          {/* 헤더 */}
          <Box sx={{ 
            display: 'flex', 
            justifyContent: 'space-between', 
            alignItems: 'center', 
            px: 1.5,
            py: 1,
            borderBottom: `1px solid ${theme.palette.divider}`,
            bgcolor: theme.palette.mode === 'dark' ? theme.palette.grey[900] : theme.palette.grey[50],
          }}>
            <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
              <Typography variant="subtitle1" fontWeight={600} fontSize="14px">
                ✏️ 전략 편집기
              </Typography>
              {selectedStrategy && (
                <Chip 
                  label={(() => {
                    try {
                      const dslData = JSON.parse(selectedStrategy.dslJson || '{}');
                      const dynamicName = generateDynamicStrategyName(dslData.buyCondition);
                      return dynamicName || selectedStrategy.name;
                    } catch (e) {
                      return selectedStrategy.name;
                    }
                  })()}
                  size="small"
                  color="primary"
                  variant="outlined"
                />
              )}
            </Box>
            <Box sx={{ display: 'flex', gap: 0.5 }}>
              <Button
                variant="outlined"
                size="small"
                startIcon={<RefreshIcon />}
                onClick={loadStrategies}
                disabled={isLoading}
              >
                새로고침
              </Button>
              <Button
                variant="outlined"
                size="small"
                startIcon={<AddIcon />}
                onClick={handleNewStrategy}
              >
                새 전략
              </Button>
              <Tooltip title="현재 전략을 JSON 파일로 내보내기">
                <span>
                  <IconButton
                    size="small"
                    onClick={handleExportStrategy}
                    disabled={!buyCondition && !sellCondition}
                    color="primary"
                    sx={{ border: `1px solid ${theme.palette.divider}` }}
                  >
                    <ExportIcon fontSize="small" />
                  </IconButton>
                </span>
              </Tooltip>
              <Tooltip title="JSON 파일에서 전략 가져오기">
                <IconButton
                  size="small"
                  onClick={handleImportStrategy}
                  color="primary"
                  sx={{ border: `1px solid ${theme.palette.divider}` }}
                >
                  <ImportIcon fontSize="small" />
                </IconButton>
              </Tooltip>
              <Tooltip title="모든 전략을 JSON 파일로 일괄 내보내기">
                <span>
                  <IconButton
                    size="small"
                    onClick={handleExportAllStrategies}
                    disabled={strategies.length === 0 || isLoading}
                    color="secondary"
                    sx={{ border: `1px solid ${theme.palette.divider}` }}
                  >
                    <ExportAllIcon fontSize="small" />
                  </IconButton>
                </span>
              </Tooltip>
              <Tooltip title="JSON 파일에서 여러 전략을 일괄 가져오기">
                <IconButton
                  size="small"
                  onClick={handleImportAllStrategies}
                  disabled={isLoading}
                  color="secondary"
                  sx={{ border: `1px solid ${theme.palette.divider}` }}
                >
                  <ImportAllIcon fontSize="small" />
                </IconButton>
              </Tooltip>
              {selectedStrategy ? (
                <Button
                  variant="contained"
                  size="small"
                  startIcon={<EditIcon />}
                  onClick={handleOpenSaveDialog}
                  disabled={!buyCondition && !sellCondition}
                  color="info"
                >
                  수정
                </Button>
              ) : (
                <Button
                  variant="contained"
                  size="small"
                  startIcon={<SaveIcon />}
                  onClick={handleOpenSaveDialog}
                  disabled={!buyCondition && !sellCondition}
                >
                  저장
                </Button>
              )}
            </Box>
          </Box>

          {/* 매수/매도 탭 */}
          <Tabs 
            value={currentTab} 
            onChange={(e, newValue) => setCurrentTab(newValue)}
            sx={{ 
              borderBottom: `1px solid ${theme.palette.divider}`,
              px: 1,
              minHeight: 42,
              '& .MuiTab-root': {
                minHeight: 42,
                py: 0.5,
                fontSize: '0.875rem',
                fontWeight: 400,
              },
              '& .Mui-selected': {
                fontSize: '1.125rem',
                fontWeight: 600,
              },
            }}
          >
            <Tab 
              label={
                <Box sx={{ 
                  display: 'flex', 
                  alignItems: 'center', 
                  gap: 0.5,
                  color: currentTab === 'buy' ? '#f44336' : 'inherit',
                }}>
                  <TrendingUp fontSize="small" />
                  매수 조건
                  {buyCondition && (
                    <Chip label="설정됨" size="small" color="success" sx={{ ml: 0.5, height: 20 }} />
                  )}
                </Box>
              } 
              value="buy"
              sx={{
                ...(currentTab === 'buy' && {
                  backgroundColor: 'rgba(244, 67, 54, 0.08)',
                }),
              }}
            />
            <Tab 
              label={
                <Box sx={{ 
                  display: 'flex', 
                  alignItems: 'center', 
                  gap: 0.5,
                  color: currentTab === 'sell' ? '#2196f3' : 'inherit',
                }}>
                  <TrendingDown fontSize="small" />
                  매도 조건
                  {sellCondition && (
                    <Chip label="설정됨" size="small" color="error" sx={{ ml: 0.5, height: 20 }} />
                  )}
                </Box>
              } 
              value="sell"
              sx={{
                ...(currentTab === 'sell' && {
                  backgroundColor: 'rgba(33, 150, 243, 0.08)',
                }),
              }}
            />
          </Tabs>

          {/* 편집기 영역 */}
          <Box sx={{ flex: 1, overflow: 'auto', p: 1 }}>
            <StrategyTreeBuilder
              rootNode={getCurrentRootNode()}
              onChange={setCurrentRootNode}
              disabled={false}
              onDropSuccess={handleDropSuccess}
              signalType={currentTab}
            />
          </Box>
        </Box>

        {/* 오른쪽 패널: 전략 목록 + 미리보기 */}
        <Box sx={{
          bgcolor: theme.palette.background.paper,
          display: 'flex',
          flexDirection: 'column',
          overflow: 'hidden',
        }}>
          {/* 탭 */}
          <Tabs 
            value={rightPanelTab} 
            onChange={(e, newValue) => setRightPanelTab(newValue)}
            sx={{ 
              borderBottom: `1px solid ${theme.palette.divider}`,
              px: 1,
              minHeight: 42,
              bgcolor: theme.palette.mode === 'dark' ? theme.palette.grey[900] : theme.palette.grey[50],
              '& .MuiTab-root': {
                minHeight: 42,
                py: 0.5,
              },
            }}
          >
            <Tab label="📋 전략목록" value="list" />
            <Tab label="📝 상세보기" value="preview" />
            <Tab label="🔔 알림목록" value="alerts" />
          </Tabs>

          {/* 전략목록 탭 */}
          {rightPanelTab === 'list' && (
            <Box sx={{ flex: 1, overflow: 'auto' }}>
            
            {isLoading ? (
              <Box sx={{ textAlign: 'center', py: 4 }}>
                <CircularProgress />
              </Box>
            ) : strategies.length === 0 ? (
              <Box sx={{ p: 2 }}>
                <Alert severity="info">저장된 전략이 없습니다</Alert>
              </Box>
            ) : (
              <>
                {/* 전략 개수 + 정렬 드롭다운 */}
                <Box
                  sx={{
                    p: 2,
                    borderBottom: `1px solid ${theme.palette.divider}`,
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'space-between',
                    gap: 1,
                    flexWrap: 'wrap',
                  }}
                >
                  <Typography variant="body2" color="text.secondary">
                    전략: {strategies.length}개
                  </Typography>
                  <FormControl size="small" sx={{ minWidth: 120 }}>
                    <Select
                      value={strategySortOrder}
                      onChange={(e) => setStrategySortOrder(e.target.value as typeof strategySortOrder)}
                      displayEmpty
                      sx={{ height: 32, fontSize: '0.8rem' }}
                    >
                      <MenuItem value="name-asc">이름(A)</MenuItem>
                      <MenuItem value="name-desc">이름(D)</MenuItem>
                      <MenuItem value="date-asc">날짜(A)</MenuItem>
                      <MenuItem value="date-desc">날짜(D)</MenuItem>
                    </Select>
                  </FormControl>
                </Box>
                <List dense sx={{ p: 0.5 }}>
                {sortedStrategies.map((strategy) => (
                  <ListItem
                    key={strategy.id}
                    button
                    selected={selectedStrategy?.id === strategy.id}
                    onClick={() => handleSelectStrategy(strategy)}
                    sx={{
                      mb: 0.5,
                      border: `1px solid ${theme.palette.divider}`,
                      py: 0.75,
                      '&.Mui-selected': {
                        backgroundColor: theme.palette.action.selected,
                        borderColor: theme.palette.primary.main,
                      },
                    }}
                  >
                    <ListItemText
                      primary={(() => {
                        try {
                          // DB에서 전략 로드 시 DSL JSON 파싱하여 조건 추출
                          const dslData = JSON.parse(strategy.dslJson || '{}');
                          const buyConditionNode = dslData.buyCondition;
                          
                          // MA 조건이면 동적 이름 생성, 아니면 원래 이름 사용
                          const dynamicName = generateDynamicStrategyName(buyConditionNode);
                          return dynamicName || strategy.name;
                        } catch (e) {
                          return strategy.name;
                        }
                      })()}
                      secondary={
                        <Box sx={{ display: 'flex', gap: 0.5, mt: 0.5 }}>
                          <Chip
                            label={strategy.strategyType === 'DSL' ? '드래그방식' : '폼방식'}
                            size="small"
                            color={strategy.strategyType === 'DSL' ? 'primary' : 'default'}
                            variant="outlined"
                          />
                          <Chip
                            label={strategy.enabled ? '활성' : '비활성'}
                            size="small"
                            color={strategy.enabled ? 'success' : 'default'}
                          />
                          {strategy.useFsm && (
                            <Chip label="FSM" size="small" color="secondary" />
                          )}
                        </Box>
                      }
                    />
                    <ListItemSecondaryAction>
                      <Tooltip title={alertStrategies.some(a => a.strategyRuleId === strategy.id) ? "알림 해제" : "알림 추가"}>
                        <IconButton
                          size="small"
                          color={alertStrategies.some(a => a.strategyRuleId === strategy.id) ? "warning" : "default"}
                          onClick={(e) => handleToggleAlert(strategy.id!, e)}
                          disabled={alertLoading}
                        >
                          {alertStrategies.some(a => a.strategyRuleId === strategy.id) ? (
                            <NotificationsActive fontSize="small" />
                          ) : (
                            <NotificationsOff fontSize="small" />
                          )}
                        </IconButton>
                      </Tooltip>
                      <Tooltip title="복제">
                        <IconButton
                          size="small"
                          onClick={(e) => {
                            e.stopPropagation();
                            handleDuplicateStrategy(strategy.id!, strategy.name);
                          }}
                        >
                          <CopyIcon fontSize="small" />
                        </IconButton>
                      </Tooltip>
                      <Tooltip title="삭제">
                        <IconButton
                          size="small"
                          onClick={(e) => {
                            e.stopPropagation();
                            setDeleteTargetId(strategy.id!);
                            setDeleteDialogOpen(true);
                          }}
                        >
                          <DeleteIcon fontSize="small" />
                        </IconButton>
                      </Tooltip>
                    </ListItemSecondaryAction>
                  </ListItem>
                ))}
              </List>
              </>
            )}
            </Box>
          )}

          {/* 상세보기 탭 */}
          {rightPanelTab === 'preview' && (
            <Box sx={{ flex: 1, overflow: 'auto', p: 1.5 }}>
              {/* 매수 조건 미리보기 (기존 유지) */}
              {buyCondition && (
                <Box sx={{ mb: 1.5 }}>
                  <Chip 
                    icon={<TrendingUp />}
                    label="매수 조건" 
                    size="small" 
                    color="success" 
                    sx={{ mb: 0.5 }}
                  />
                  <Box
                    sx={{
                      p: 1.5,
                      backgroundColor: theme.palette.mode === 'dark' ? 
                        theme.palette.grey[800] : 
                        theme.palette.grey[100],
                      border: `1px solid ${theme.palette.divider}`,
                      fontFamily: 'monospace',
                      fontSize: '0.8rem',
                      lineHeight: 1.5,
                      whiteSpace: 'pre-wrap',
                    }}
                  >
                    {nodeToNaturalLanguage(buyCondition)}
                  </Box>
                </Box>
              )}

              {/* 매도 조건 미리보기 (기존 유지) */}
              {sellCondition && (
                <Box sx={{ mb: 2 }}>
                  <Chip 
                    icon={<TrendingDown />}
                    label="매도 조건" 
                    size="small" 
                    color="error" 
                    sx={{ mb: 0.5 }}
                  />
                  <Box
                    sx={{
                      p: 1.5,
                      backgroundColor: theme.palette.mode === 'dark' ? 
                        theme.palette.grey[800] : 
                        theme.palette.grey[100],
                      border: `1px solid ${theme.palette.divider}`,
                      fontFamily: 'monospace',
                      fontSize: '0.8rem',
                      lineHeight: 1.5,
                      whiteSpace: 'pre-wrap',
                    }}
                  >
                    {nodeToNaturalLanguage(sellCondition)}
                  </Box>
                </Box>
              )}

              {/* ━━━ 코드 로직 ━━━ (새로 추가) */}
              {(buyCondition || sellCondition) && (
                <Box sx={{ mb: 2 }}>
                  <Typography 
                    variant="subtitle2" 
                    sx={{ 
                      mb: 1,
                      fontWeight: 600,
                      color: theme.palette.primary.main,
                      borderBottom: `2px solid ${theme.palette.divider}`,
                      pb: 0.5
                    }}
                  >
                    ━━━ 코드 로직 ━━━
                  </Typography>

                  {/* 매수 신호 수식 */}
                  {buyCondition && (
                    <Box sx={{ mb: 1.5 }}>
                      <Typography 
                        variant="body2" 
                        sx={{ 
                          fontFamily: 'monospace',
                          fontSize: '0.8rem',
                          mb: 0.5
                        }}
                      >
                        <span style={{ color: theme.palette.success.main, fontWeight: 600 }}>매수 신호</span> = {nodeToLogicFormula(buyCondition)}
                      </Typography>
                    </Box>
                  )}

                  {/* 매도 신호 수식 */}
                  {sellCondition && (
                    <Box>
                      <Typography 
                        variant="body2" 
                        sx={{ 
                          fontFamily: 'monospace',
                          fontSize: '0.8rem'
                        }}
                      >
                        <span style={{ color: theme.palette.error.main, fontWeight: 600 }}>매도 신호</span> = {nodeToLogicFormula(sellCondition)}
                      </Typography>
                    </Box>
                  )}
                </Box>
              )}

              {/* ━━━ 검증 결과 ━━━ */}
              {(buyCondition || sellCondition) && (
                <Box>
                  <Typography 
                    variant="subtitle2" 
                    sx={{ 
                      mb: 1,
                      fontWeight: 600,
                      color: theme.palette.primary.main,
                      borderBottom: `2px solid ${theme.palette.divider}`,
                      pb: 0.5
                    }}
                  >
                    ━━━ 검증 결과 ━━━
                  </Typography>

                  {/* 매수 조건 검증 결과 */}
                  {buyCondition && buyValidation && (
                    <Box sx={{ mb: 1.5 }}>
                      <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, mb: 0.5 }}>
                        <TrendingUp fontSize="small" />
                        <Typography variant="body2" sx={{ fontWeight: 600 }}>
                          매수 조건
                        </Typography>
                      </Box>
                      
                      {buyValidation.isValid ? (
                        <Alert 
                          severity="success" 
                          icon={<CheckIcon />}
                          sx={{ py: 0.5 }}
                        >
                          논리적 오류가 없습니다
                        </Alert>
                      ) : (
                        <Box>
                          {buyValidation.errors.length > 0 && (
                            <Alert 
                              severity="error" 
                              icon={<ErrorIcon />}
                              sx={{ mb: 0.5, py: 0.5 }}
                            >
                              <Typography variant="body2" sx={{ fontWeight: 600, mb: 0.5 }}>
                                오류 ({buyValidation.errors.length}개)
                              </Typography>
                              {buyValidation.errors.map((error, idx) => (
                                <Typography 
                                  key={idx} 
                                  variant="caption" 
                                  component="div"
                                  sx={{ ml: 1, mt: 0.5 }}
                                >
                                  • {error.message}
                                </Typography>
                              ))}
                            </Alert>
                          )}
                        </Box>
                      )}

                      {buyValidation.warnings.length > 0 && (
                        <Alert 
                          severity="warning" 
                          sx={{ mt: 0.5, py: 0.5 }}
                        >
                          <Typography variant="body2" sx={{ fontWeight: 600, mb: 0.5 }}>
                            경고 ({buyValidation.warnings.length}개)
                          </Typography>
                          {buyValidation.warnings.map((warning, idx) => (
                            <Typography 
                              key={idx} 
                              variant="caption" 
                              component="div"
                              sx={{ ml: 1, mt: 0.5 }}
                            >
                              • {warning.message}
                            </Typography>
                          ))}
                        </Alert>
                      )}
                    </Box>
                  )}

                  {/* 매도 조건 검증 결과 */}
                  {sellCondition && sellValidation && (
                    <Box>
                      <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, mb: 0.5 }}>
                        <TrendingDown fontSize="small" />
                        <Typography variant="body2" sx={{ fontWeight: 600 }}>
                          매도 조건
                        </Typography>
                      </Box>
                      
                      {sellValidation.isValid ? (
                        <Alert 
                          severity="success" 
                          icon={<CheckIcon />}
                          sx={{ py: 0.5 }}
                        >
                          논리적 오류가 없습니다
                        </Alert>
                      ) : (
                        <Box>
                          {sellValidation.errors.length > 0 && (
                            <Alert 
                              severity="error" 
                              icon={<ErrorIcon />}
                              sx={{ mb: 0.5, py: 0.5 }}
                            >
                              <Typography variant="body2" sx={{ fontWeight: 600, mb: 0.5 }}>
                                오류 ({sellValidation.errors.length}개)
                              </Typography>
                              {sellValidation.errors.map((error, idx) => (
                                <Typography 
                                  key={idx} 
                                  variant="caption" 
                                  component="div"
                                  sx={{ ml: 1, mt: 0.5 }}
                                >
                                  • {error.message}
                                </Typography>
                              ))}
                            </Alert>
                          )}
                        </Box>
                      )}

                      {sellValidation.warnings.length > 0 && (
                        <Alert 
                          severity="warning" 
                          sx={{ mt: 0.5, py: 0.5 }}
                        >
                          <Typography variant="body2" sx={{ fontWeight: 600, mb: 0.5 }}>
                            경고 ({sellValidation.warnings.length}개)
                          </Typography>
                          {sellValidation.warnings.map((warning, idx) => (
                            <Typography 
                              key={idx} 
                              variant="caption" 
                              component="div"
                              sx={{ ml: 1, mt: 0.5 }}
                            >
                              • {warning.message}
                            </Typography>
                          ))}
                        </Alert>
                      )}
                    </Box>
                  )}
                </Box>
              )}

              {!buyCondition && !sellCondition && (
                <Alert severity="info" sx={{ m: 0 }}>
                  매수 또는 매도 조건을 추가하세요
                </Alert>
              )}
            </Box>
          )}

          {/* 알림목록 탭 */}
          {rightPanelTab === 'alerts' && (
            <Box sx={{ flex: 1, overflow: 'auto' }}>
              {alertLoading ? (
                <Box sx={{ textAlign: 'center', py: 4 }}>
                  <CircularProgress />
                </Box>
              ) : (
                <>
                  {/* 알림 전략 개수 표시 + 정렬 드롭다운 */}
                  <Box
                    sx={{
                      p: 2,
                      borderBottom: `1px solid ${theme.palette.divider}`,
                      display: 'flex',
                      alignItems: 'center',
                      justifyContent: 'space-between',
                      gap: 1,
                      flexWrap: 'wrap',
                    }}
                  >
                    <Typography variant="body2" color="text.secondary">
                      알림 활성화된 전략: {alertStrategies.length}개
                    </Typography>
                    <FormControl size="small" sx={{ minWidth: 120 }}>
                      <Select
                        value={alertSortOrder}
                        onChange={(e) => setAlertSortOrder(e.target.value as typeof alertSortOrder)}
                        displayEmpty
                        sx={{ height: 32, fontSize: '0.8rem' }}
                      >
                        <MenuItem value="name-asc">이름(A)</MenuItem>
                        <MenuItem value="name-desc">이름(D)</MenuItem>
                        <MenuItem value="date-asc">날짜(A)</MenuItem>
                        <MenuItem value="date-desc">날짜(D)</MenuItem>
                      </Select>
                    </FormControl>
                  </Box>

                  {alertStrategies.length === 0 ? (
                    <Box sx={{ p: 2 }}>
                      <Alert severity="info">
                        알림이 활성화된 전략이 없습니다.
                        <br />
                        목록에서 🔔 아이콘을 클릭하여 알림을 활성화하세요.
                      </Alert>
                    </Box>
                  ) : (
                    <List sx={{ pt: 0 }}>
                      {sortedAlertStrategies.map((alertStrategy) => {
                        // 전략 정보 찾기
                        const strategy = strategies.find(s => s.id === alertStrategy.strategyRuleId);
                        
                        return (
                          <ListItem
                            key={alertStrategy.id}
                            sx={{
                              borderBottom: `1px solid ${theme.palette.divider}`,
                              '&:hover': {
                                bgcolor: theme.palette.action.hover,
                              },
                            }}
                          >
                            <ListItemText
                              primary={
                                <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
                                  <Typography variant="body1" sx={{ fontWeight: 500 }}>
                                    {alertStrategy.strategyRuleName || strategy?.name || '알 수 없는 전략'}
                                  </Typography>
                                  <Chip
                                    label={strategy?.strategyType === 'DSL' ? 'DSL' : 'LEGACY'}
                                    size="small"
                                    color={strategy?.strategyType === 'DSL' ? 'primary' : 'default'}
                                    sx={{ height: 20, fontSize: '0.7rem' }}
                                  />
                                </Box>
                              }
                              secondary={
                                <Box sx={{ mt: 0.5 }}>
                                  <Typography variant="caption" color="text.secondary" component="div">
                                    전략 ID: {alertStrategy.strategyRuleId}
                                  </Typography>
                                  {strategy?.description && (
                                    <Typography variant="caption" color="text.secondary" component="div" sx={{ mt: 0.5 }}>
                                      {strategy.description}
                                    </Typography>
                                  )}
                                </Box>
                              }
                            />
                            <ListItemSecondaryAction>
                              <Tooltip title="알림 해제">
                                <IconButton
                                  edge="end"
                                  onClick={(e) => handleToggleAlert(alertStrategy.strategyRuleId, e)}
                                  disabled={alertLoading}
                                  color="error"
                                  size="small"
                                >
                                  <NotificationsOff />
                                </IconButton>
                              </Tooltip>
                            </ListItemSecondaryAction>
                          </ListItem>
                        );
                      })}
                    </List>
                  )}
                </>
              )}
            </Box>
          )}
        </Box>
      </Box>

      {/* 저장/수정 다이얼로그 */}
      <Dialog open={saveDialogOpen} onClose={() => setSaveDialogOpen(false)} maxWidth="sm" fullWidth>
        <DialogTitle>
          {selectedStrategy ? '전략 수정' : '전략 저장'}
        </DialogTitle>
        <DialogContent>
          {selectedStrategy && (
            <Alert severity="info" sx={{ mb: 2 }}>
              기존 전략 "{selectedStrategy.name}"을(를) 수정합니다.
            </Alert>
          )}
          
          {/* 매수/매도 조건 상태 표시 */}
          <Box sx={{ mb: 2, display: 'flex', gap: 1 }}>
            <Chip 
              icon={<TrendingUp />}
              label={buyCondition ? '매수 조건 설정됨' : '매수 조건 없음'}
              size="small" 
              color={buyCondition ? 'success' : 'default'}
              variant={buyCondition ? 'filled' : 'outlined'}
            />
            <Chip 
              icon={<TrendingDown />}
              label={sellCondition ? '매도 조건 설정됨' : '매도 조건 없음'}
              size="small" 
              color={sellCondition ? 'error' : 'default'}
              variant={sellCondition ? 'filled' : 'outlined'}
            />
          </Box>

          <TextField
            label="전략 이름"
            value={strategyName}
            onChange={(e) => setStrategyName(e.target.value)}
            fullWidth
            margin="normal"
            required
          />
          <TextField
            label="설명 (선택사항)"
            value={strategyDescription}
            onChange={(e) => setStrategyDescription(e.target.value)}
            fullWidth
            margin="normal"
            multiline
            rows={3}
          />
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setSaveDialogOpen(false)}>취소</Button>
          <Button
            onClick={handleSaveStrategy}
            variant="contained"
            startIcon={selectedStrategy ? <EditIcon /> : <SaveIcon />}
            disabled={isSaving || !strategyName.trim()}
            color={selectedStrategy ? 'info' : 'primary'}
          >
            {isSaving ? 
              (selectedStrategy ? '수정 중...' : '저장 중...') : 
              (selectedStrategy ? '수정' : '저장')
            }
          </Button>
        </DialogActions>
      </Dialog>

      {/* 삭제 확인 다이얼로그 */}
      <Dialog open={deleteDialogOpen} onClose={() => setDeleteDialogOpen(false)}>
        <DialogTitle>전략 삭제</DialogTitle>
        <DialogContent>
          <Typography>정말로 이 전략을 삭제하시겠습니까?</Typography>
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setDeleteDialogOpen(false)}>취소</Button>
          <Button
            onClick={() => deleteTargetId && handleDeleteStrategy(deleteTargetId)}
            color="error"
            variant="contained"
          >
            삭제
          </Button>
        </DialogActions>
      </Dialog>

      {/* 스낵바 */}
      <Snackbar
        open={snackbarOpen}
        autoHideDuration={3000}
        onClose={() => setSnackbarOpen(false)}
        anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
      >
        <Alert
          onClose={() => setSnackbarOpen(false)}
          severity={snackbarSeverity}
          icon={snackbarSeverity === 'success' ? <CheckIcon /> : <ErrorIcon />}
        >
          {snackbarMessage}
        </Alert>
      </Snackbar>

      {/* 드래그 오버레이 - 드래그 중인 항목 표시 */}
      <DragOverlay dropAnimation={dropAnimation}>
        {activeDragItem ? (
          <Chip
            label={
              <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
                {activeDragItem.type === 'operator' ? <TreeIcon fontSize="small" /> : <ChartIcon fontSize="small" />}
                {activeDragItem.label}
              </Box>
            }
            sx={{
              cursor: 'grabbing',
              backgroundColor: activeDragItem.type === 'operator' ? 
                (activeDragItem.value === 'AND' ? theme.palette.success.main :
                 activeDragItem.value === 'OR' ? theme.palette.info.main :
                 theme.palette.warning.main) : 
                theme.palette.secondary.main,
              color: theme.palette.primary.contrastText,
              fontWeight: 'bold',
              fontSize: '0.9rem',
              boxShadow: theme.shadows[8],
              transform: 'scale(1.05)',
            }}
          />
        ) : null}
      </DragOverlay>
    </DndContext>
  );
};

export default StrategyTreeBuilderPage;
