"use client";

import React, { useMemo, useState, useCallback, useRef } from "react";
import { useDrag, useDrop } from "react-dnd";
import { cn } from "@/lib/utils";
import {
  PopLayoutDataV4,
  PopContainerV4,
  PopComponentDefinitionV4,
  PopResponsiveRuleV4,
  PopSizeConstraintV4,
  PopComponentType,
} from "../types/pop-layout";

// 드래그 아이템 타입
const DND_COMPONENT_REORDER = "POP_COMPONENT_REORDER";

interface DragItem {
  type: string;
  componentId: string;
  containerId: string;
  index: number;
}

// ========================================
// Props 정의
// ========================================

interface PopFlexRendererProps {
  /** v4 레이아웃 데이터 */
  layout: PopLayoutDataV4;
  /** 현재 뷰포트 너비 (반응형 규칙 적용용) */
  viewportWidth: number;
  /** 디자인 모드 여부 */
  isDesignMode?: boolean;
  /** 선택된 컴포넌트 ID */
  selectedComponentId?: string | null;
  /** 컴포넌트 클릭 */
  onComponentClick?: (componentId: string) => void;
  /** 컨테이너 클릭 */
  onContainerClick?: (containerId: string) => void;
  /** 배경 클릭 */
  onBackgroundClick?: () => void;
  /** 컴포넌트 크기 변경 */
  onComponentResize?: (componentId: string, size: Partial<PopSizeConstraintV4>) => void;
  /** 컴포넌트 순서 변경 */
  onReorderComponent?: (containerId: string, fromIndex: number, toIndex: number) => void;
  /** 추가 className */
  className?: string;
}

// ========================================
// 컴포넌트 타입별 라벨
// ========================================
const COMPONENT_TYPE_LABELS: Record<PopComponentType, string> = {
  "pop-field": "필드",
  "pop-button": "버튼",
  "pop-list": "리스트",
  "pop-indicator": "인디케이터",
  "pop-scanner": "스캐너",
  "pop-numpad": "숫자패드",
  "pop-spacer": "스페이서",
};

// ========================================
// v4 Flexbox 렌더러
// 
// 핵심 역할:
// - v4 레이아웃을 Flexbox CSS로 렌더링
// - 제약조건(fill/fixed/hug) 기반 크기 계산
// - 반응형 규칙(breakpoint) 자동 적용
// ========================================

export function PopFlexRenderer({
  layout,
  viewportWidth,
  isDesignMode = false,
  selectedComponentId,
  onComponentClick,
  onContainerClick,
  onBackgroundClick,
  onComponentResize,
  onReorderComponent,
  className,
}: PopFlexRendererProps) {
  const { root, components, settings } = layout;

  // 빈 상태는 PopCanvasV4에서 표시하므로 여기서는 투명 배경만 렌더링
  if (root.children.length === 0) {
    return (
      <div
        className={cn("h-full w-full", className)}
        onClick={onBackgroundClick}
      />
    );
  }

  return (
    <div
      className={cn("relative min-h-full w-full bg-white", className)}
      onClick={(e) => {
        if (e.target === e.currentTarget) {
          onBackgroundClick?.();
        }
      }}
    >
      {/* 루트 컨테이너 렌더링 */}
      <ContainerRenderer
        container={root}
        components={components}
        viewportWidth={viewportWidth}
        settings={settings}
        isDesignMode={isDesignMode}
        selectedComponentId={selectedComponentId}
        onComponentClick={onComponentClick}
        onContainerClick={onContainerClick}
        onComponentResize={onComponentResize}
        onReorderComponent={onReorderComponent}
      />
    </div>
  );
}

// ========================================
// 컨테이너 렌더러 (재귀)
// ========================================

interface ContainerRendererProps {
  container: PopContainerV4;
  components: Record<string, PopComponentDefinitionV4>;
  viewportWidth: number;
  settings: PopLayoutDataV4["settings"];
  isDesignMode?: boolean;
  selectedComponentId?: string | null;
  onComponentClick?: (componentId: string) => void;
  onContainerClick?: (containerId: string) => void;
  onComponentResize?: (componentId: string, size: Partial<PopSizeConstraintV4>) => void;
  onReorderComponent?: (containerId: string, fromIndex: number, toIndex: number) => void;
  depth?: number;
}

function ContainerRenderer({
  container,
  components,
  viewportWidth,
  settings,
  isDesignMode = false,
  selectedComponentId,
  onComponentClick,
  onContainerClick,
  onComponentResize,
  onReorderComponent,
  depth = 0,
}: ContainerRendererProps) {
  // 반응형 규칙 적용
  const effectiveContainer = useMemo(() => {
    return applyResponsiveRules(container, viewportWidth);
  }, [container, viewportWidth]);

  // 비율 스케일 계산 (디자인 모드에서는 1, 뷰어에서는 실제 비율 적용)
  const scale = isDesignMode ? 1 : viewportWidth / BASE_VIEWPORT_WIDTH;

  // Flexbox 스타일 계산 (useMemo는 조건문 전에 호출해야 함)
  const containerStyle = useMemo((): React.CSSProperties => {
    const { direction, wrap, gap, alignItems, justifyContent, padding } = effectiveContainer;

    // gap과 padding도 스케일 적용
    const scaledGap = gap * scale;
    const scaledPadding = padding ? padding * scale : undefined;

    return {
      display: "flex",
      flexDirection: direction === "horizontal" ? "row" : "column",
      flexWrap: wrap ? "wrap" : "nowrap",
      gap: `${scaledGap}px`,
      alignItems: mapAlignment(alignItems),
      justifyContent: mapJustify(justifyContent),
      padding: scaledPadding ? `${scaledPadding}px` : undefined,
      width: "100%",
      minHeight: depth === 0 ? "100%" : undefined,
    };
  }, [effectiveContainer, depth, scale]);

  // 숨김 처리
  if (effectiveContainer.hidden) {
    return null;
  }

  return (
    <div
      className={cn(
        "relative",
        isDesignMode && depth > 0 && "border border-dashed border-gray-300 rounded"
      )}
      style={containerStyle}
      onClick={(e) => {
        if (e.target === e.currentTarget) {
          onContainerClick?.(container.id);
        }
      }}
    >
      {effectiveContainer.children.map((child, index) => {
        // 중첩 컨테이너인 경우
        if (typeof child === "object") {
          return (
            <ContainerRenderer
              key={child.id}
              container={child}
              components={components}
              viewportWidth={viewportWidth}
              settings={settings}
              isDesignMode={isDesignMode}
              selectedComponentId={selectedComponentId}
              onComponentClick={onComponentClick}
              onContainerClick={onContainerClick}
              onComponentResize={onComponentResize}
              onReorderComponent={onReorderComponent}
              depth={depth + 1}
            />
          );
        }

        // 컴포넌트 ID인 경우
        const componentId = child;
        const compDef = components[componentId];
        if (!compDef) return null;

        // 반응형 숨김 처리
        if (compDef.hideBelow && viewportWidth < compDef.hideBelow) {
          return null;
        }

        return (
          <DraggableComponentWrapper
            key={componentId}
            componentId={componentId}
            containerId={container.id}
            index={index}
            isDesignMode={isDesignMode}
            onReorder={onReorderComponent}
          >
            <ComponentRendererV4
              componentId={componentId}
              component={compDef}
              settings={settings}
              viewportWidth={viewportWidth}
              isDesignMode={isDesignMode}
              isSelected={selectedComponentId === componentId}
              onClick={() => onComponentClick?.(componentId)}
              onResize={onComponentResize}
            />
          </DraggableComponentWrapper>
        );
      })}
    </div>
  );
}

// ========================================
// 드래그 가능한 컴포넌트 래퍼
// ========================================

interface DraggableComponentWrapperProps {
  componentId: string;
  containerId: string;
  index: number;
  isDesignMode: boolean;
  onReorder?: (containerId: string, fromIndex: number, toIndex: number) => void;
  children: React.ReactNode;
}

function DraggableComponentWrapper({
  componentId,
  containerId,
  index,
  isDesignMode,
  onReorder,
  children,
}: DraggableComponentWrapperProps) {
  // 디자인 모드가 아니면 그냥 children 반환 (훅 호출 전에 체크)
  // DndProvider가 없는 환경에서 useDrag/useDrop 훅 호출 방지
  if (!isDesignMode) {
    return <>{children}</>;
  }

  // 디자인 모드일 때만 드래그 기능 활성화
  return (
    <DraggableComponentWrapperInner
      componentId={componentId}
      containerId={containerId}
      index={index}
      onReorder={onReorder}
    >
      {children}
    </DraggableComponentWrapperInner>
  );
}

// 디자인 모드 전용 내부 컴포넌트 (DndProvider 필요)
function DraggableComponentWrapperInner({
  componentId,
  containerId,
  index,
  onReorder,
  children,
}: Omit<DraggableComponentWrapperProps, "isDesignMode">) {
  const ref = useRef<HTMLDivElement>(null);

  const [{ isDragging }, drag] = useDrag({
    type: DND_COMPONENT_REORDER,
    item: (): DragItem => ({
      type: DND_COMPONENT_REORDER,
      componentId,
      containerId,
      index,
    }),
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });

  const [{ isOver, canDrop }, drop] = useDrop({
    accept: DND_COMPONENT_REORDER,
    canDrop: (item: DragItem) => {
      // 같은 컨테이너 내에서만 이동 가능 (일단은)
      return item.containerId === containerId && item.index !== index;
    },
    drop: (item: DragItem) => {
      if (item.index !== index && onReorder) {
        onReorder(containerId, item.index, index);
      }
    },
    collect: (monitor) => ({
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop(),
    }),
  });

  // drag와 drop 합치기
  drag(drop(ref));

  return (
    <div
      ref={ref}
      className={cn(
        "relative",
        isDragging && "opacity-50",
        isOver && canDrop && "ring-2 ring-blue-500 ring-offset-2"
      )}
      style={{ cursor: isDragging ? "grabbing" : "grab" }}
    >
      {children}
      {/* 드롭 인디케이터 */}
      {isOver && canDrop && (
        <div className="absolute inset-0 bg-blue-500/10 pointer-events-none rounded" />
      )}
    </div>
  );
}

// ========================================
// v4 컴포넌트 렌더러 (리사이즈 핸들 포함)
// ========================================

interface ComponentRendererV4Props {
  componentId: string;
  component: PopComponentDefinitionV4;
  settings: PopLayoutDataV4["settings"];
  viewportWidth: number;
  isDesignMode?: boolean;
  isSelected?: boolean;
  onClick?: () => void;
  onResize?: (componentId: string, size: Partial<PopSizeConstraintV4>) => void;
}

function ComponentRendererV4({
  componentId,
  component,
  settings,
  viewportWidth,
  isDesignMode = false,
  isSelected = false,
  onClick,
  onResize,
}: ComponentRendererV4Props) {
  const { size, alignSelf, type, label } = component;
  const containerRef = useRef<HTMLDivElement>(null);
  
  // 비율 스케일 계산 (디자인 모드에서는 1, 뷰어에서는 실제 비율 적용)
  const scale = isDesignMode ? 1 : viewportWidth / BASE_VIEWPORT_WIDTH;
  
  // 리사이즈 상태
  const [isResizing, setIsResizing] = useState(false);
  const [resizeDirection, setResizeDirection] = useState<"width" | "height" | "both" | null>(null);
  const resizeStartRef = useRef<{ x: number; y: number; width: number; height: number } | null>(null);

  // 크기 스타일 계산 (스케일 적용)
  const sizeStyle = useMemo((): React.CSSProperties => {
    return calculateSizeStyle(size, settings, scale);
  }, [size, settings, scale]);

  // alignSelf 스타일
  const alignStyle: React.CSSProperties = alignSelf
    ? { alignSelf: mapAlignment(alignSelf) }
    : {};

  const typeLabel = COMPONENT_TYPE_LABELS[type] || type;

  // 리사이즈 시작
  const handleResizeStart = useCallback((
    e: React.MouseEvent,
    direction: "width" | "height" | "both"
  ) => {
    e.stopPropagation();
    e.preventDefault();
    
    if (!containerRef.current) return;
    
    const rect = containerRef.current.getBoundingClientRect();
    resizeStartRef.current = {
      x: e.clientX,
      y: e.clientY,
      width: rect.width,
      height: rect.height,
    };
    setIsResizing(true);
    setResizeDirection(direction);
  }, []);

  // 리사이즈 중
  useCallback((e: MouseEvent) => {
    if (!isResizing || !resizeStartRef.current || !onResize) return;
    
    const deltaX = e.clientX - resizeStartRef.current.x;
    const deltaY = e.clientY - resizeStartRef.current.y;
    
    const updates: Partial<PopSizeConstraintV4> = {};
    
    if (resizeDirection === "width" || resizeDirection === "both") {
      const newWidth = Math.max(48, Math.round(resizeStartRef.current.width + deltaX));
      updates.width = "fixed";
      updates.fixedWidth = newWidth;
    }
    
    if (resizeDirection === "height" || resizeDirection === "both") {
      const newHeight = Math.max(settings.touchTargetMin, Math.round(resizeStartRef.current.height + deltaY));
      updates.height = "fixed";
      updates.fixedHeight = newHeight;
    }
    
    onResize(componentId, updates);
  }, [isResizing, resizeDirection, componentId, onResize, settings.touchTargetMin]);

  // 리사이즈 종료 및 이벤트 등록
  React.useEffect(() => {
    if (!isResizing) return;

    const handleMouseMove = (e: MouseEvent) => {
      if (!resizeStartRef.current || !onResize) return;
      
      const deltaX = e.clientX - resizeStartRef.current.x;
      const deltaY = e.clientY - resizeStartRef.current.y;
      
      const updates: Partial<PopSizeConstraintV4> = {};
      
      if (resizeDirection === "width" || resizeDirection === "both") {
        const newWidth = Math.max(48, Math.round(resizeStartRef.current.width + deltaX));
        updates.width = "fixed";
        updates.fixedWidth = newWidth;
      }
      
      if (resizeDirection === "height" || resizeDirection === "both") {
        const newHeight = Math.max(settings.touchTargetMin, Math.round(resizeStartRef.current.height + deltaY));
        updates.height = "fixed";
        updates.fixedHeight = newHeight;
      }
      
      onResize(componentId, updates);
    };

    const handleMouseUp = () => {
      setIsResizing(false);
      setResizeDirection(null);
      resizeStartRef.current = null;
    };

    window.addEventListener("mousemove", handleMouseMove);
    window.addEventListener("mouseup", handleMouseUp);

    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
      window.removeEventListener("mouseup", handleMouseUp);
    };
  }, [isResizing, resizeDirection, componentId, onResize, settings.touchTargetMin]);

  return (
    <div
      ref={containerRef}
      className={cn(
        "relative flex flex-col overflow-visible rounded-lg border-2 bg-white transition-all",
        isSelected
          ? "border-primary ring-2 ring-primary/30 z-10"
          : "border-gray-200",
        isDesignMode && !isResizing && "cursor-pointer hover:border-gray-300",
        isResizing && "select-none"
      )}
      style={{
        ...sizeStyle,
        ...alignStyle,
      }}
      onClick={(e) => {
        e.stopPropagation();
        if (!isResizing) {
          onClick?.();
        }
      }}
    >
      {/* 컴포넌트 라벨 (디자인 모드에서만) */}
      {isDesignMode && (
        <div
          className={cn(
            "flex h-5 shrink-0 items-center border-b px-2",
            isSelected ? "bg-primary/10" : "bg-gray-50"
          )}
        >
          <span className="text-[10px] font-medium text-gray-600">
            {label || typeLabel}
          </span>
        </div>
      )}

      {/* 컴포넌트 내용 */}
      <div className="flex flex-1 items-center justify-center p-2 overflow-hidden">
        {renderComponentContent(component, isDesignMode, settings)}
      </div>

      {/* 리사이즈 핸들 (디자인 모드 + 선택 시에만) */}
      {isDesignMode && isSelected && onResize && (
        <>
          {/* 오른쪽 핸들 (너비 조정) */}
          <div
            className="absolute right-0 top-1/2 -translate-y-1/2 translate-x-1/2 w-3 h-8 bg-primary rounded cursor-ew-resize hover:bg-primary/80 flex items-center justify-center z-20"
            onMouseDown={(e) => handleResizeStart(e, "width")}
            title="너비 조정"
          >
            <div className="w-0.5 h-4 bg-white rounded" />
          </div>

          {/* 아래쪽 핸들 (높이 조정) */}
          <div
            className="absolute bottom-0 left-1/2 -translate-x-1/2 translate-y-1/2 h-3 w-8 bg-primary rounded cursor-ns-resize hover:bg-primary/80 flex items-center justify-center z-20"
            onMouseDown={(e) => handleResizeStart(e, "height")}
            title="높이 조정"
          >
            <div className="h-0.5 w-4 bg-white rounded" />
          </div>

          {/* 오른쪽 아래 핸들 (너비 + 높이 동시 조정) */}
          <div
            className="absolute right-0 bottom-0 translate-x-1/2 translate-y-1/2 w-4 h-4 bg-primary rounded cursor-nwse-resize hover:bg-primary/80 flex items-center justify-center z-20"
            onMouseDown={(e) => handleResizeStart(e, "both")}
            title="크기 조정"
          >
            <div className="w-2 h-2 border-r-2 border-b-2 border-white" />
          </div>
        </>
      )}
    </div>
  );
}

// ========================================
// 헬퍼 함수들
// ========================================

/**
 * 반응형 규칙 적용
 */
function applyResponsiveRules(
  container: PopContainerV4,
  viewportWidth: number
): PopContainerV4 & { hidden?: boolean } {
  if (!container.responsive || container.responsive.length === 0) {
    return container;
  }

  // 현재 뷰포트에 적용되는 규칙 찾기 (가장 큰 breakpoint부터)
  const sortedRules = [...container.responsive].sort((a, b) => b.breakpoint - a.breakpoint);
  const applicableRule = sortedRules.find((rule) => viewportWidth <= rule.breakpoint);

  if (!applicableRule) {
    return container;
  }

  return {
    ...container,
    direction: applicableRule.direction ?? container.direction,
    gap: applicableRule.gap ?? container.gap,
    hidden: applicableRule.hidden ?? false,
  };
}

/**
 * 기준 뷰포트 너비 (10인치 태블릿 가로)
 * 이 크기를 기준으로 컴포넌트 크기가 비율 조정됨
 */
const BASE_VIEWPORT_WIDTH = 1024;

/**
 * 크기 제약 → CSS 스타일 변환
 * @param scale - 뷰포트 비율 (viewportWidth / BASE_VIEWPORT_WIDTH)
 */
function calculateSizeStyle(
  size: PopSizeConstraintV4,
  settings: PopLayoutDataV4["settings"],
  scale: number = 1
): React.CSSProperties {
  const style: React.CSSProperties = {};

  // 스케일된 터치 최소 크기
  const scaledTouchMin = settings.touchTargetMin * scale;

  // 너비
  switch (size.width) {
    case "fixed":
      // fixed 크기도 비율에 맞게 스케일
      style.width = size.fixedWidth ? `${size.fixedWidth * scale}px` : "auto";
      style.flexShrink = 0;
      break;
    case "fill":
      style.flex = 1;
      style.minWidth = size.minWidth ? `${size.minWidth * scale}px` : 0;
      style.maxWidth = size.maxWidth ? `${size.maxWidth * scale}px` : undefined;
      break;
    case "hug":
      style.width = "auto";
      style.flexShrink = 0;
      break;
  }

  // 높이
  switch (size.height) {
    case "fixed":
      const scaledFixedHeight = (size.fixedHeight || settings.touchTargetMin) * scale;
      const minHeight = Math.max(scaledFixedHeight, scaledTouchMin);
      style.height = `${minHeight}px`;
      break;
    case "fill":
      style.flexGrow = 1;
      style.minHeight = size.minHeight
        ? `${Math.max(size.minHeight * scale, scaledTouchMin)}px`
        : `${scaledTouchMin}px`;
      break;
    case "hug":
      style.height = "auto";
      style.minHeight = `${scaledTouchMin}px`;
      break;
  }

  return style;
}

/**
 * alignItems 값 변환
 */
function mapAlignment(value: string): React.CSSProperties["alignItems"] {
  switch (value) {
    case "start":
      return "flex-start";
    case "end":
      return "flex-end";
    case "center":
      return "center";
    case "stretch":
      return "stretch";
    default:
      return "stretch";
  }
}

/**
 * justifyContent 값 변환
 */
function mapJustify(value: string): React.CSSProperties["justifyContent"] {
  switch (value) {
    case "start":
      return "flex-start";
    case "end":
      return "flex-end";
    case "center":
      return "center";
    case "space-between":
      return "space-between";
    default:
      return "flex-start";
  }
}

/**
 * 컴포넌트별 내용 렌더링
 */
function renderComponentContent(
  component: PopComponentDefinitionV4,
  isDesignMode: boolean,
  settings: PopLayoutDataV4["settings"]
): React.ReactNode {
  const typeLabel = COMPONENT_TYPE_LABELS[component.type] || component.type;

  // 디자인 모드에서는 플레이스홀더 표시
  if (isDesignMode) {
    // Spacer는 디자인 모드에서 점선 배경으로 표시
    if (component.type === "pop-spacer") {
      return (
        <div className="h-full w-full flex items-center justify-center border-2 border-dashed border-gray-300 bg-gray-50/50 rounded">
          <span className="text-xs text-gray-400">빈 공간</span>
        </div>
      );
    }
    return (
      <div className="text-xs text-gray-400 text-center">
        {typeLabel}
      </div>
    );
  }

  // 뷰어 모드: 실제 컴포넌트 렌더링
  switch (component.type) {
    case "pop-field":
      return (
        <input
          type="text"
          placeholder={component.label || "입력하세요"}
          className="w-full h-full px-3 py-2 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-primary"
        />
      );

    case "pop-button":
      return (
        <button className="w-full h-full px-4 py-2 text-sm font-medium text-white bg-primary rounded-md hover:bg-primary/90 transition-colors">
          {component.label || "버튼"}
        </button>
      );

    case "pop-list":
      return (
        <div className="w-full h-full overflow-auto p-2">
          <div className="text-xs text-gray-500 text-center">
            리스트 (데이터 연결 필요)
          </div>
        </div>
      );

    case "pop-indicator":
      return (
        <div className="text-center">
          <div className="text-2xl font-bold text-primary">0</div>
          <div className="text-xs text-gray-500">{component.label || "지표"}</div>
        </div>
      );

    case "pop-scanner":
      return (
        <div className="text-center text-gray-500">
          <div className="text-xs">스캐너</div>
          <div className="text-[10px]">탭하여 스캔</div>
        </div>
      );

    case "pop-numpad":
      return (
        <div className="grid grid-cols-3 gap-1 p-1 w-full">
          {[1, 2, 3, 4, 5, 6, 7, 8, 9, "C", 0, "OK"].map((key) => (
            <button
              key={key}
              className="aspect-square text-xs font-medium bg-gray-100 rounded hover:bg-gray-200"
            >
              {key}
            </button>
          ))}
        </div>
      );

    case "pop-spacer":
      // 실제 모드에서 Spacer는 완전히 투명 (공간만 차지)
      return null;

    default:
      return (
        <div className="text-xs text-gray-400">
          {typeLabel}
        </div>
      );
  }
}

export default PopFlexRenderer;
