import React, { useRef, useState, useEffect, useCallback } from 'react';
import { Box, IconButton, Tooltip, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material';
import {
  Create as DrawIcon,
  Timeline as LineIcon,
  Gesture as FreeDrawIcon,
  ShowChart as TrendIcon,
  Delete as ClearIcon,
  Undo as UndoIcon,
  Redo as RedoIcon,
  GridOn as GridIcon,
} from '@mui/icons-material';

interface Point {
  x: number;
  y: number;
}

interface PatternCanvasProps {
  width?: number;
  height?: number;
  isDark?: boolean;
  onPatternChange?: (patternData: number[]) => void;
  templatePattern?: number[];
  showGrid?: boolean;
}

type DrawingTool = 'select' | 'freedraw' | 'line' | 'trend';

const PatternCanvas: React.FC<PatternCanvasProps> = ({
  width = 800,
  height = 400,
  isDark = true,
  onPatternChange,
  templatePattern,
  showGrid: initialShowGrid = true,
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  
  const [isDrawing, setIsDrawing] = useState(false);
  const [currentTool, setCurrentTool] = useState<DrawingTool>('freedraw');
  const [paths, setPaths] = useState<Point[][]>([]);
  const [currentPath, setCurrentPath] = useState<Point[]>([]);
  const [undoStack, setUndoStack] = useState<Point[][][]>([]);
  const [redoStack, setRedoStack] = useState<Point[][][]>([]);
  const [showGrid, setShowGrid] = useState(initialShowGrid);
  
  // 직선/추세선 클릭 기반 그리기 상태
  const [linePoints, setLinePoints] = useState<Point[]>([]); // 확정된 점들
  const [previewPoint, setPreviewPoint] = useState<Point | null>(null); // 마우스 위치 (미리보기용)
  const [isLineDrawing, setIsLineDrawing] = useState(false); // 직선 그리기 모드 활성화 여부
  
  // 색상 설정
  const colors = {
    background: isDark ? '#18181b' : '#f5f5f5',
    grid: isDark ? '#27272a' : '#e0e0e0',
    line: isDark ? '#22c55e' : '#16a34a',
    templateLine: isDark ? '#3b82f6' : '#2563eb',
    previewLine: isDark ? '#f59e0b' : '#d97706',
    axis: isDark ? '#52525b' : '#9ca3af',
  };
  
  // 캔버스 크기 조정
  const [canvasSize, setCanvasSize] = useState({ width, height });
  
  useEffect(() => {
    const updateSize = () => {
      if (containerRef.current) {
        const rect = containerRef.current.getBoundingClientRect();
        setCanvasSize({
          width: rect.width || width,
          height: rect.height || height,
        });
      }
    };
    
    updateSize();
    window.addEventListener('resize', updateSize);
    return () => window.removeEventListener('resize', updateSize);
  }, [width, height]);
  
  // 캔버스 그리기
  const drawCanvas = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    
    const ctx = canvas.getContext('2d');
    if (!ctx) return;
    
    // 캔버스 클리어
    ctx.fillStyle = colors.background;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    
    // 그리드 그리기
    if (showGrid) {
      ctx.strokeStyle = colors.grid;
      ctx.lineWidth = 1;
      
      const gridSize = 40;
      for (let x = 0; x <= canvas.width; x += gridSize) {
        ctx.beginPath();
        ctx.moveTo(x, 0);
        ctx.lineTo(x, canvas.height);
        ctx.stroke();
      }
      for (let y = 0; y <= canvas.height; y += gridSize) {
        ctx.beginPath();
        ctx.moveTo(0, y);
        ctx.lineTo(canvas.width, y);
        ctx.stroke();
      }
    }
    
    // 템플릿 패턴 그리기
    if (templatePattern && templatePattern.length > 1) {
      ctx.strokeStyle = colors.templateLine;
      ctx.lineWidth = 3;
      ctx.lineCap = 'round';
      ctx.lineJoin = 'round';
      ctx.setLineDash([8, 4]);
      
      ctx.beginPath();
      const padding = 40;
      const drawWidth = canvas.width - padding * 2;
      const drawHeight = canvas.height - padding * 2;
      
      templatePattern.forEach((value, index) => {
        const x = padding + (index / (templatePattern.length - 1)) * drawWidth;
        const y = padding + (1 - value) * drawHeight;
        
        if (index === 0) {
          ctx.moveTo(x, y);
        } else {
          ctx.lineTo(x, y);
        }
      });
      ctx.stroke();
      ctx.setLineDash([]);
    }
    
    // 저장된 경로 그리기
    ctx.strokeStyle = colors.line;
    ctx.lineWidth = 3;
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    
    paths.forEach(path => {
      if (path.length < 2) return;
      
      ctx.beginPath();
      ctx.moveTo(path[0].x, path[0].y);
      
      for (let i = 1; i < path.length; i++) {
        ctx.lineTo(path[i].x, path[i].y);
      }
      ctx.stroke();
    });
    
    // 현재 그리고 있는 자유 곡선
    if (currentPath.length > 1 && currentTool === 'freedraw') {
      ctx.strokeStyle = colors.line;
      ctx.lineWidth = 3;
      ctx.beginPath();
      ctx.moveTo(currentPath[0].x, currentPath[0].y);
      
      for (let i = 1; i < currentPath.length; i++) {
        ctx.lineTo(currentPath[i].x, currentPath[i].y);
      }
      ctx.stroke();
    }
    
    // 직선/추세선 모드: 확정된 점들 연결
    if (linePoints.length > 1) {
      ctx.strokeStyle = colors.line;
      ctx.lineWidth = 3;
      ctx.lineCap = 'round';
      ctx.lineJoin = 'round';
      ctx.beginPath();
      ctx.moveTo(linePoints[0].x, linePoints[0].y);
      
      for (let i = 1; i < linePoints.length; i++) {
        ctx.lineTo(linePoints[i].x, linePoints[i].y);
      }
      ctx.stroke();
    }
    
    // 직선/추세선 모드: 미리보기 선 (마지막 확정 점 → 마우스 위치)
    if (isLineDrawing && linePoints.length > 0 && previewPoint) {
      const lastPoint = linePoints[linePoints.length - 1];
      
      ctx.strokeStyle = colors.previewLine;
      ctx.lineWidth = 2;
      ctx.setLineDash([5, 5]);
      ctx.beginPath();
      ctx.moveTo(lastPoint.x, lastPoint.y);
      ctx.lineTo(previewPoint.x, previewPoint.y);
      ctx.stroke();
      ctx.setLineDash([]);
      
      // 마우스 위치에 점 표시
      ctx.fillStyle = colors.previewLine;
      ctx.beginPath();
      ctx.arc(previewPoint.x, previewPoint.y, 4, 0, Math.PI * 2);
      ctx.fill();
    }
    
    // 확정된 점들에 마커 표시
    if (linePoints.length > 0) {
      ctx.fillStyle = colors.line;
      linePoints.forEach((point, index) => {
        ctx.beginPath();
        ctx.arc(point.x, point.y, index === 0 ? 6 : 4, 0, Math.PI * 2);
        ctx.fill();
      });
    }
    
  }, [paths, currentPath, templatePattern, showGrid, colors, linePoints, previewPoint, isLineDrawing, currentTool]);
  
  useEffect(() => {
    drawCanvas();
  }, [drawCanvas, canvasSize]);
  
  // 마우스 이벤트 핸들러
  const getMousePos = (e: React.MouseEvent<HTMLCanvasElement>): Point => {
    const canvas = canvasRef.current;
    if (!canvas) return { x: 0, y: 0 };
    
    const rect = canvas.getBoundingClientRect();
    return {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top,
    };
  };
  
  // 직선/추세선 그리기 완료 (경로 저장)
  const finishLineDrawing = useCallback(() => {
    if (linePoints.length > 1) {
      // 현재 상태를 undo 스택에 저장
      setUndoStack(prev => [...prev, paths]);
      setRedoStack([]);
      
      // 새 경로 추가
      const newPaths = [...paths, linePoints];
      setPaths(newPaths);
      
      // 패턴 데이터 추출 및 콜백
      extractPatternData(newPaths);
    }
    
    setLinePoints([]);
    setPreviewPoint(null);
    setIsLineDrawing(false);
  }, [linePoints, paths]);
  
  const handleMouseDown = (e: React.MouseEvent<HTMLCanvasElement>) => {
    if (currentTool === 'select') return;
    
    // 우클릭: 직선/추세선 그리기 종료
    if (e.button === 2) {
      e.preventDefault();
      if ((currentTool === 'line' || currentTool === 'trend') && isLineDrawing) {
        finishLineDrawing();
      }
      return;
    }
    
    const pos = getMousePos(e);
    
    if (currentTool === 'line' || currentTool === 'trend') {
      // 직선/추세선: 클릭으로 점 추가
      if (!isLineDrawing) {
        // 첫 번째 클릭: 그리기 시작
        setIsLineDrawing(true);
        setLinePoints([pos]);
      } else {
        // 이후 클릭: 점 추가 (이전 점과 연결)
        setLinePoints(prev => [...prev, pos]);
      }
    } else {
      // 자유 곡선: 드래그 방식
      setIsDrawing(true);
      setCurrentPath([pos]);
    }
  };
  
  const handleMouseMove = (e: React.MouseEvent<HTMLCanvasElement>) => {
    const pos = getMousePos(e);
    
    if (currentTool === 'line' || currentTool === 'trend') {
      // 직선/추세선: 미리보기 업데이트
      if (isLineDrawing) {
        setPreviewPoint(pos);
      }
    } else {
      // 자유 곡선: 드래그 중 점 추가
      if (isDrawing) {
        setCurrentPath(prev => [...prev, pos]);
      }
    }
  };
  
  const handleMouseUp = () => {
    // 자유 곡선만 마우스업에서 처리
    if (currentTool === 'freedraw' && isDrawing) {
      setIsDrawing(false);
      
      if (currentPath.length > 1) {
        // 현재 상태를 undo 스택에 저장
        setUndoStack(prev => [...prev, paths]);
        setRedoStack([]);
        
        // 새 경로 추가
        const newPaths = [...paths, currentPath];
        setPaths(newPaths);
        
        // 패턴 데이터 추출 및 콜백
        extractPatternData(newPaths);
      }
      
      setCurrentPath([]);
    }
  };
  
  const handleMouseLeave = () => {
    if (currentTool === 'freedraw' && isDrawing) {
      handleMouseUp();
    }
    // 직선/추세선 모드에서는 마우스가 나가도 계속 유지
  };
  
  // 우클릭 메뉴 방지
  const handleContextMenu = (e: React.MouseEvent<HTMLCanvasElement>) => {
    e.preventDefault();
    
    // 직선/추세선 모드에서 우클릭으로 그리기 종료
    if ((currentTool === 'line' || currentTool === 'trend') && isLineDrawing) {
      finishLineDrawing();
    }
  };
  
  // 패턴 데이터 추출 (Y 좌표를 정규화된 값으로 변환)
  const extractPatternData = (allPaths: Point[][]) => {
    if (!onPatternChange) return;
    
    const canvas = canvasRef.current;
    if (!canvas) return;
    
    // 모든 경로의 점들을 하나로 합치고 X 좌표로 정렬
    const allPoints: Point[] = allPaths.flat().sort((a, b) => a.x - b.x);
    
    if (allPoints.length < 2) {
      onPatternChange([]);
      return;
    }
    
    // 일정 간격으로 샘플링
    const sampleCount = 20;
    const minX = allPoints[0].x;
    const maxX = allPoints[allPoints.length - 1].x;
    const step = (maxX - minX) / (sampleCount - 1);
    
    const sampledData: number[] = [];
    
    for (let i = 0; i < sampleCount; i++) {
      const targetX = minX + step * i;
      
      // 가장 가까운 점 찾기
      let closestPoint = allPoints[0];
      let minDist = Math.abs(allPoints[0].x - targetX);
      
      for (const point of allPoints) {
        const dist = Math.abs(point.x - targetX);
        if (dist < minDist) {
          minDist = dist;
          closestPoint = point;
        }
      }
      
      // Y 좌표를 0-1로 정규화 (위가 1, 아래가 0)
      const normalizedY = 1 - (closestPoint.y / canvas.height);
      sampledData.push(normalizedY);
    }
    
    onPatternChange(sampledData);
  };
  
  // 실행 취소
  const handleUndo = () => {
    if (undoStack.length === 0) return;
    
    // 직선 그리기 중이면 먼저 취소
    if (isLineDrawing) {
      setLinePoints([]);
      setPreviewPoint(null);
      setIsLineDrawing(false);
      return;
    }
    
    const previousState = undoStack[undoStack.length - 1];
    setRedoStack(prev => [...prev, paths]);
    setPaths(previousState);
    setUndoStack(prev => prev.slice(0, -1));
    extractPatternData(previousState);
  };
  
  // 다시 실행
  const handleRedo = () => {
    if (redoStack.length === 0) return;
    
    const nextState = redoStack[redoStack.length - 1];
    setUndoStack(prev => [...prev, paths]);
    setPaths(nextState);
    setRedoStack(prev => prev.slice(0, -1));
    extractPatternData(nextState);
  };
  
  // 전체 지우기
  const handleClear = () => {
    // 진행 중인 직선 그리기 취소
    if (isLineDrawing) {
      setLinePoints([]);
      setPreviewPoint(null);
      setIsLineDrawing(false);
    }
    
    if (paths.length === 0) return;
    
    setUndoStack(prev => [...prev, paths]);
    setRedoStack([]);
    setPaths([]);
    setCurrentPath([]);
    onPatternChange?.([]);
  };
  
  // 도구 변경
  const handleToolChange = (_: React.MouseEvent<HTMLElement>, newTool: DrawingTool | null) => {
    if (newTool) {
      // 도구 변경 시 진행 중인 그리기 완료
      if (isLineDrawing) {
        finishLineDrawing();
      }
      setCurrentTool(newTool);
    }
  };
  
  // 키보드 이벤트 (ESC로 취소)
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape' && isLineDrawing) {
        setLinePoints([]);
        setPreviewPoint(null);
        setIsLineDrawing(false);
      }
    };
    
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [isLineDrawing]);
  
  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
      {/* 도구 모음 */}
      <Box sx={{
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'space-between',
        p: 1,
        borderBottom: `1px solid ${isDark ? '#27272a' : '#e0e0e0'}`,
        bgcolor: isDark ? '#1f1f26' : '#fafafa',
      }}>
        <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
          <ToggleButtonGroup
            value={currentTool}
            exclusive
            onChange={handleToolChange}
            size="small"
            sx={{
              '& .MuiToggleButton-root': {
                color: isDark ? '#a1a1aa' : '#666',
                borderColor: isDark ? '#3f3f46' : '#d0d0d0',
                '&.Mui-selected': {
                  color: '#fff',
                  bgcolor: '#3b82f6',
                  '&:hover': { bgcolor: '#2563eb' },
                },
              },
            }}
          >
            <ToggleButton value="freedraw">
              <Tooltip title="자유 곡선 (드래그)">
                <FreeDrawIcon fontSize="small" />
              </Tooltip>
            </ToggleButton>
            <ToggleButton value="line">
              <Tooltip title="직선 (클릭으로 점 연결, 우클릭으로 완료)">
                <LineIcon fontSize="small" />
              </Tooltip>
            </ToggleButton>
            <ToggleButton value="trend">
              <Tooltip title="추세선 (클릭으로 점 연결, 우클릭으로 완료)">
                <TrendIcon fontSize="small" />
              </Tooltip>
            </ToggleButton>
          </ToggleButtonGroup>
          
          <Box sx={{ width: 1, height: 24, bgcolor: isDark ? '#3f3f46' : '#d0d0d0', mx: 1 }} />
          
          <Tooltip title="실행 취소 (ESC: 취소)">
            <IconButton 
              size="small" 
              onClick={handleUndo} 
              disabled={undoStack.length === 0 && !isLineDrawing}
              sx={{ color: isDark ? '#a1a1aa' : '#666' }}
            >
              <UndoIcon fontSize="small" />
            </IconButton>
          </Tooltip>
          
          <Tooltip title="다시 실행">
            <IconButton 
              size="small" 
              onClick={handleRedo} 
              disabled={redoStack.length === 0}
              sx={{ color: isDark ? '#a1a1aa' : '#666' }}
            >
              <RedoIcon fontSize="small" />
            </IconButton>
          </Tooltip>
          
          <Tooltip title="전체 지우기">
            <IconButton 
              size="small" 
              onClick={handleClear}
              disabled={paths.length === 0 && !isLineDrawing}
              sx={{ color: isDark ? '#a1a1aa' : '#666' }}
            >
              <ClearIcon fontSize="small" />
            </IconButton>
          </Tooltip>
        </Box>
        
        <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
          {isLineDrawing && (
            <Typography sx={{ 
              fontSize: '11px', 
              color: colors.previewLine,
              fontWeight: 600,
            }}>
              그리기 중... (우클릭으로 완료)
            </Typography>
          )}
          
          <Tooltip title={showGrid ? '그리드 숨기기' : '그리드 표시'}>
            <IconButton 
              size="small" 
              onClick={() => setShowGrid(!showGrid)}
              sx={{ 
                color: showGrid ? '#3b82f6' : (isDark ? '#a1a1aa' : '#666'),
              }}
            >
              <GridIcon fontSize="small" />
            </IconButton>
          </Tooltip>
          
          <Typography sx={{ fontSize: '11px', color: isDark ? '#71717a' : '#888' }}>
            {paths.length > 0 || linePoints.length > 0
              ? `${paths.reduce((sum, p) => sum + p.length, 0) + linePoints.length}개 포인트` 
              : '그리기 시작'}
          </Typography>
        </Box>
      </Box>
      
      {/* 캔버스 영역 */}
      <Box 
        ref={containerRef}
        sx={{ 
          flex: 1, 
          position: 'relative',
          cursor: currentTool === 'select' ? 'default' : 'crosshair',
        }}
      >
        <canvas
          ref={canvasRef}
          width={canvasSize.width}
          height={canvasSize.height}
          onMouseDown={handleMouseDown}
          onMouseMove={handleMouseMove}
          onMouseUp={handleMouseUp}
          onMouseLeave={handleMouseLeave}
          onContextMenu={handleContextMenu}
          style={{
            display: 'block',
            width: '100%',
            height: '100%',
          }}
        />
        
        {/* 빈 캔버스 힌트 */}
        {paths.length === 0 && !isDrawing && !isLineDrawing && (
          <Box sx={{
            position: 'absolute',
            top: '50%',
            left: '50%',
            transform: 'translate(-50%, -50%)',
            textAlign: 'center',
            pointerEvents: 'none',
          }}>
            <DrawIcon sx={{ fontSize: 48, color: isDark ? '#3f3f46' : '#d0d0d0', mb: 1 }} />
            <Typography sx={{ fontSize: '14px', color: isDark ? '#52525b' : '#9ca3af' }}>
              마우스로 패턴을 그려주세요
            </Typography>
            <Typography sx={{ fontSize: '12px', color: isDark ? '#3f3f46' : '#d0d0d0', mt: 0.5 }}>
              자유곡선: 드래그 | 직선/추세선: 클릭 → 우클릭 완료
            </Typography>
          </Box>
        )}
      </Box>
    </Box>
  );
};

export default PatternCanvas;
