"use client";

import React, { useMemo } from "react";
import { useDrag } from "react-dnd";
import { cn } from "@/lib/utils";
import { DND_ITEM_TYPES } from "../constants";
import {
  PopLayoutData,
  PopComponentDefinition,
  PopGridPosition,
  GridMode,
  GRID_BREAKPOINTS,
  GridBreakpoint,
  detectGridMode,
  PopComponentType,
  BLOCK_SIZE,
  BLOCK_GAP,
  BLOCK_PADDING,
  getBlockColumns,
} from "../types/pop-layout";
import { 
  convertAndResolvePositions,
  isOverlapping,
  getAllEffectivePositions,
} from "../utils/gridUtils";
import { PopComponentRegistry } from "@/lib/registry/PopComponentRegistry";

// ========================================
// Props
// ========================================

interface PopRendererProps {
  /** v5 레이아웃 데이터 */
  layout: PopLayoutData;
  /** 현재 뷰포트 너비 */
  viewportWidth: number;
  /** 현재 모드 (자동 감지 또는 수동 지정) */
  currentMode?: GridMode;
  /** 디자인 모드 여부 */
  isDesignMode?: boolean;
  /** 그리드 가이드 표시 여부 */
  showGridGuide?: boolean;
  /** 선택된 컴포넌트 ID */
  selectedComponentId?: string | null;
  /** 컴포넌트 클릭 */
  onComponentClick?: (componentId: string) => void;
  /** 배경 클릭 */
  onBackgroundClick?: () => void;
  /** 컴포넌트 이동 */
  onComponentMove?: (componentId: string, newPosition: PopGridPosition) => void;
  /** 컴포넌트 크기 조정 */
  onComponentResize?: (componentId: string, newPosition: PopGridPosition) => void;
  /** 컴포넌트 크기 조정 완료 (히스토리 저장용) */
  onComponentResizeEnd?: (componentId: string) => void;
  /** 컴포넌트가 자신의 rowSpan/colSpan 변경을 요청 (CardList 확장 등) */
  onRequestResize?: (componentId: string, newRowSpan: number, newColSpan?: number) => void;
  /** Gap 오버라이드 (Gap 프리셋 적용된 값) */
  overrideGap?: number;
  /** Padding 오버라이드 (Gap 프리셋 적용된 값) */
  overridePadding?: number;
  /** 추가 className */
  className?: string;
  /** 현재 편집 중인 화면 ID (아이콘 네비게이션용) */
  currentScreenId?: number;
  /** 대시보드 페이지 미리보기 인덱스 */
  previewPageIndex?: number;
}

// ========================================
// 컴포넌트 타입별 라벨
// ========================================

const COMPONENT_TYPE_LABELS: Record<PopComponentType, string> = {
  "pop-sample": "샘플",
  "pop-text": "텍스트",
  "pop-icon": "아이콘",
  "pop-dashboard": "대시보드",
  "pop-card-list": "장바구니 목록",
  "pop-card-list-v2": "MES 공정흐름",
  "pop-button": "버튼",
  "pop-string-list": "리스트 목록",
  "pop-search": "검색",
  "pop-status-bar": "상태 바",
  "pop-field": "입력",
  "pop-scanner": "스캐너",
  "pop-profile": "프로필",
  "pop-work-detail": "작업 상세",
};

// ========================================
// PopRenderer: v5 그리드 렌더러
// ========================================

export default function PopRenderer({
  layout,
  viewportWidth,
  currentMode,
  isDesignMode = false,
  showGridGuide = true,
  selectedComponentId,
  onComponentClick,
  onBackgroundClick,
  onComponentMove,
  onComponentResize,
  onComponentResizeEnd,
  onRequestResize,
  overrideGap,
  overridePadding,
  className,
  currentScreenId,
  previewPageIndex,
}: PopRendererProps) {
  const { gridConfig, components, overrides } = layout;
  
  // V6: 뷰포트 너비에서 블록 칸 수 동적 계산
  const mode = currentMode || detectGridMode(viewportWidth);
  const columns = getBlockColumns(viewportWidth);
  
  // V6: 블록 간격 고정
  const finalGap = overrideGap !== undefined ? overrideGap : BLOCK_GAP;
  const finalPadding = overridePadding !== undefined ? overridePadding : BLOCK_PADDING;
  
  // 하위 호환: breakpoint 객체 (ResizeHandles 등에서 사용)
  const breakpoint: GridBreakpoint = {
    columns,
    rowHeight: BLOCK_SIZE,
    gap: finalGap,
    padding: finalPadding,
    label: `${columns}칸 블록`,
  };
  
  // 숨김 컴포넌트 ID 목록
  const hiddenIds = overrides?.[mode]?.hidden || [];
  
  // 동적 행 수 계산
  const dynamicRowCount = useMemo(() => {
    const visibleComps = Object.values(components).filter(
      comp => !hiddenIds.includes(comp.id)
    );
    const maxRowEnd = visibleComps.reduce((max, comp) => {
      const override = overrides?.[mode]?.positions?.[comp.id];
      const pos = override ? { ...comp.position, ...override } : comp.position;
      return Math.max(max, pos.row + pos.rowSpan);
    }, 1);
    return Math.max(10, maxRowEnd + 3);
  }, [components, overrides, mode, hiddenIds]);
  
  // V6: CSS Grid - 열은 1fr(뷰포트 꽉 채움), 행은 고정 BLOCK_SIZE (디자이너/뷰어 동일 = WYSIWYG)
  const rowTemplate = `repeat(${dynamicRowCount}, ${BLOCK_SIZE}px)`;
  const autoRowHeight = `${BLOCK_SIZE}px`;

  const gridStyle = useMemo((): React.CSSProperties => ({
    display: "grid",
    gridTemplateColumns: `repeat(${columns}, 1fr)`,
    gridTemplateRows: rowTemplate,
    gridAutoRows: autoRowHeight,
    gap: `${finalGap}px`,
    padding: `${finalPadding}px`,
    minHeight: "100%",
    backgroundColor: "hsl(var(--background))",
    position: "relative",
  }), [columns, finalGap, finalPadding, dynamicRowCount, rowTemplate, autoRowHeight]);
  
  // 그리드 가이드 셀 생성
  const gridCells = useMemo(() => {
    if (!isDesignMode || !showGridGuide) return [];
    
    const cells = [];
    for (let row = 1; row <= dynamicRowCount; row++) {
      for (let col = 1; col <= columns; col++) {
        cells.push({ 
          id: `cell-${col}-${row}`, 
          col, 
          row 
        });
      }
    }
    return cells;
  }, [isDesignMode, showGridGuide, columns, dynamicRowCount]);
  
  // visibility 체크
  const isVisible = (comp: PopComponentDefinition): boolean => {
    if (!comp.visibility) return true;
    const modeVisibility = comp.visibility[mode];
    return modeVisibility !== false;
  };
  
  // 자동 재배치된 위치 계산 (오버라이드 없을 때)
  const autoResolvedPositions = useMemo(() => {
    const componentsArray = Object.entries(components).map(([id, comp]) => ({
      id,
      position: comp.position,
    }));
    
    return convertAndResolvePositions(componentsArray, mode);
  }, [components, mode]);
  
  // 위치 변환 (12칸 기준 → 현재 모드 칸 수)
  const convertPosition = (position: PopGridPosition): React.CSSProperties => {
    return {
      gridColumn: `${position.col} / span ${position.colSpan}`,
      gridRow: `${position.row} / span ${position.rowSpan}`,
    };
  };
  
  // 오버라이드 적용 또는 자동 재배치
  const getEffectivePosition = (comp: PopComponentDefinition): PopGridPosition => {
    // 1순위: 오버라이드가 있으면 사용
    const override = overrides?.[mode]?.positions?.[comp.id];
    if (override) {
      return { ...comp.position, ...override };
    }
    
    // 2순위: 자동 재배치된 위치 사용
    const autoResolved = autoResolvedPositions.find(p => p.id === comp.id);
    if (autoResolved) {
      return autoResolved.position;
    }
    
    // 3순위: 원본 위치 (12칸 모드)
    return comp.position;
  };
  
  // 오버라이드 숨김 체크
  const isHiddenByOverride = (comp: PopComponentDefinition): boolean => {
    return overrides?.[mode]?.hidden?.includes(comp.id) ?? false;
  };
  
  // 모든 컴포넌트의 유효 위치 계산 (리사이즈 겹침 검사용)
  const effectivePositionsMap = useMemo(() => 
    getAllEffectivePositions(layout, mode),
    [layout, mode]
  );
  
  return (
    <div
      className={cn("relative min-h-full w-full", className)}
      style={gridStyle}
      onClick={(e) => {
        if (e.target === e.currentTarget) {
          onBackgroundClick?.();
        }
      }}
    >
      {/* 그리드 가이드 셀 (실제 DOM) */}
      {gridCells.map(cell => (
        <div
          key={cell.id}
          className="pointer-events-none border border-dashed border-primary/40/40"
          style={{
            gridColumn: cell.col,
            gridRow: cell.row,
          }}
        />
      ))}
      
      {/* 컴포넌트 렌더링 (z-index로 위에 표시) */}
      {/* v5.1: 자동 줄바꿈으로 모든 컴포넌트가 그리드 안에 배치됨 */}
      {Object.values(components).map((comp) => {
        // visibility 체크
        if (!isVisible(comp)) return null;
        
        // 오버라이드 숨김 체크
        if (isHiddenByOverride(comp)) return null;
        
        const position = getEffectivePosition(comp);
        const positionStyle = convertPosition(position);
        const isSelected = selectedComponentId === comp.id;
        
        // 디자인 모드에서는 드래그 가능한 컴포넌트, 뷰어 모드에서는 일반 컴포넌트
        if (isDesignMode) {
          return (
            <DraggableComponent
              key={comp.id}
              component={comp}
              position={position}
              positionStyle={positionStyle}
              isSelected={isSelected}
              isDesignMode={isDesignMode}
              breakpoint={breakpoint}
              viewportWidth={viewportWidth}
              allEffectivePositions={effectivePositionsMap}
              effectiveGap={finalGap}
              effectivePadding={finalPadding}
              onComponentClick={onComponentClick}
              onComponentMove={onComponentMove}
              onComponentResize={onComponentResize}
              onComponentResizeEnd={onComponentResizeEnd}
              onRequestResize={onRequestResize}
              previewPageIndex={previewPageIndex}
            />
          );
        }
        
        // 콘텐츠 영역 컴포넌트는 라운드 테두리 표시
        const contentTypes = new Set([
          "pop-dashboard", "pop-card-list", "pop-card-list-v2",
          "pop-string-list", "pop-work-detail", "pop-sample",
        ]);
        const needsBorder = contentTypes.has(comp.type);

        return (
          <div
            key={comp.id}
            className={cn(
              "relative overflow-hidden transition-all z-10",
              needsBorder && "rounded-lg border border-border/40 bg-card"
            )}
            style={positionStyle}
          >
            <ComponentContent 
              component={comp}
              effectivePosition={position}
              isDesignMode={false}
              isSelected={false}
              onRequestResize={onRequestResize}
              screenId={currentScreenId ? String(currentScreenId) : undefined}
            />
          </div>
        );
      })}
    </div>
  );
}

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

interface DraggableComponentProps {
  component: PopComponentDefinition;
  position: PopGridPosition;
  positionStyle: React.CSSProperties;
  isSelected: boolean;
  isDesignMode: boolean;
  breakpoint: GridBreakpoint;
  viewportWidth: number;
  allEffectivePositions: Map<string, PopGridPosition>;
  effectiveGap: number;
  effectivePadding: number;
  onComponentClick?: (componentId: string) => void;
  onComponentMove?: (componentId: string, newPosition: PopGridPosition) => void;
  onComponentResize?: (componentId: string, newPosition: PopGridPosition) => void;
  onComponentResizeEnd?: (componentId: string) => void;
  onRequestResize?: (componentId: string, newRowSpan: number, newColSpan?: number) => void;
  previewPageIndex?: number;
}

function DraggableComponent({
  component,
  position,
  positionStyle,
  isSelected,
  isDesignMode,
  breakpoint,
  viewportWidth,
  allEffectivePositions,
  effectiveGap,
  effectivePadding,
  onComponentClick,
  onComponentMove,
  onComponentResize,
  onComponentResizeEnd,
  onRequestResize,
  previewPageIndex,
}: DraggableComponentProps) {
  const [{ isDragging }, drag] = useDrag(
    () => ({
      type: DND_ITEM_TYPES.MOVE_COMPONENT,
      item: { 
        componentId: component.id, 
        originalPosition: position 
      },
      canDrag: isDesignMode,
      collect: (monitor) => ({
        isDragging: monitor.isDragging(),
      }),
    }),
    [component.id, position, isDesignMode]
  );
  
  return (
    <div
      ref={isDesignMode ? drag : null}
      className={cn(
        "relative rounded-lg border-2 transition-all overflow-hidden z-10 bg-white",
        isSelected
          ? "border-primary ring-2 ring-primary/30"
          : "border-border",
        isDesignMode && "cursor-move hover:border-input hover:shadow-sm",
        isDragging && "opacity-50"
      )}
      style={positionStyle}
      onClick={(e) => {
        e.stopPropagation();
        onComponentClick?.(component.id);
      }}
    >
      <ComponentContent 
        component={component}
        effectivePosition={position}
        isDesignMode={isDesignMode}
        isSelected={isSelected}
        previewPageIndex={previewPageIndex}
        onRequestResize={onRequestResize}
        screenId={undefined}
      />
      
      {/* 리사이즈 핸들 (선택된 컴포넌트만) */}
      {isDesignMode && isSelected && onComponentResize && (
        <ResizeHandles
          component={component}
          position={position}
          breakpoint={breakpoint}
          viewportWidth={viewportWidth}
          allEffectivePositions={allEffectivePositions}
          effectiveGap={effectiveGap}
          effectivePadding={effectivePadding}
          onResize={onComponentResize}
          onResizeEnd={onComponentResizeEnd}
        />
      )}
    </div>
  );
}

// ========================================
// 리사이즈 핸들
// ========================================

interface ResizeHandlesProps {
  component: PopComponentDefinition;
  position: PopGridPosition;
  breakpoint: GridBreakpoint;
  viewportWidth: number;
  allEffectivePositions: Map<string, PopGridPosition>;
  effectiveGap: number;
  effectivePadding: number;
  onResize: (componentId: string, newPosition: PopGridPosition) => void;
  onResizeEnd?: (componentId: string) => void;
}

function ResizeHandles({
  component,
  position,
  breakpoint,
  viewportWidth,
  allEffectivePositions,
  effectiveGap,
  effectivePadding,
  onResize,
  onResizeEnd,
}: ResizeHandlesProps) {
  const handleMouseDown = (direction: 'right' | 'bottom' | 'corner') => (e: React.MouseEvent) => {
    e.stopPropagation();
    e.preventDefault();
    
    const startX = e.clientX;
    const startY = e.clientY;
    const startColSpan = position.colSpan;
    const startRowSpan = position.rowSpan;
    
    // 그리드 셀 크기 동적 계산 (Gap 프리셋 적용된 값 사용)
    // 사용 가능한 너비 = 뷰포트 너비 - 양쪽 패딩 - gap*(칸수-1)
    const availableWidth = viewportWidth - effectivePadding * 2 - effectiveGap * (breakpoint.columns - 1);
    const cellWidth = availableWidth / breakpoint.columns + effectiveGap; // 셀 너비 + gap 단위
    const cellHeight = breakpoint.rowHeight + effectiveGap;
    
    const handleMouseMove = (e: MouseEvent) => {
      const deltaX = e.clientX - startX;
      const deltaY = e.clientY - startY;
      
      let newColSpan = startColSpan;
      let newRowSpan = startRowSpan;
      
      if (direction === 'right' || direction === 'corner') {
        const colDelta = Math.round(deltaX / cellWidth);
        newColSpan = Math.max(1, startColSpan + colDelta);
        // 최대 칸 수 제한
        newColSpan = Math.min(newColSpan, breakpoint.columns - position.col + 1);
      }
      
      if (direction === 'bottom' || direction === 'corner') {
        const rowDelta = Math.round(deltaY / cellHeight);
        newRowSpan = Math.max(1, startRowSpan + rowDelta);
      }
      
      // 변경사항이 있으면 업데이트
      if (newColSpan !== position.colSpan || newRowSpan !== position.rowSpan) {
        const newPosition: PopGridPosition = {
          ...position,
          colSpan: newColSpan,
          rowSpan: newRowSpan,
        };
        
        // 유효 위치 기반 겹침 검사 (다른 컴포넌트와)
        const hasOverlap = Array.from(allEffectivePositions.entries()).some(
          ([id, pos]) => {
            if (id === component.id) return false;  // 자기 자신 제외
            return isOverlapping(newPosition, pos);
          }
        );
        
        // 겹치지 않을 때만 리사이즈 적용
        if (!hasOverlap) {
          onResize(component.id, newPosition);
        }
      }
    };
    
    const handleMouseUp = () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
      // 리사이즈 완료 알림 (히스토리 저장용)
      onResizeEnd?.(component.id);
    };
    
    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
  };
  
  return (
    <>
      {/* 오른쪽 핸들 (가로 크기) */}
      <div
        className="absolute top-0 bottom-0 w-2 cursor-ew-resize bg-primary/20 hover:bg-primary/50 transition-colors"
        onMouseDown={handleMouseDown('right')}
        style={{ right: '-4px' }}
      />
      
      {/* 아래쪽 핸들 (세로 크기) */}
      <div
        className="absolute left-0 right-0 h-2 cursor-ns-resize bg-primary/20 hover:bg-primary/50 transition-colors"
        onMouseDown={handleMouseDown('bottom')}
        style={{ bottom: '-4px' }}
      />
      
      {/* 오른쪽 아래 모서리 (가로+세로) */}
      <div
        className="absolute h-3 w-3 cursor-nwse-resize bg-primary hover:bg-primary/80 transition-colors rounded-sm"
        onMouseDown={handleMouseDown('corner')}
        style={{ right: '-6px', bottom: '-6px' }}
      />
    </>
  );
}

// ========================================
// 컴포넌트 내용 렌더링
// ========================================

interface ComponentContentProps {
  component: PopComponentDefinition;
  effectivePosition: PopGridPosition;
  isDesignMode: boolean;
  isSelected: boolean;
  previewPageIndex?: number;
  onRequestResize?: (componentId: string, newRowSpan: number, newColSpan?: number) => void;
  /** 화면 ID (이벤트 버스/액션 실행용) */
  screenId?: string;
}

function ComponentContent({ component, effectivePosition, isDesignMode, isSelected, previewPageIndex, onRequestResize, screenId }: ComponentContentProps) {
  const typeLabel = COMPONENT_TYPE_LABELS[component.type] || component.type;
  
  // PopComponentRegistry에서 등록된 컴포넌트 가져오기
  const registeredComp = PopComponentRegistry.getComponent(component.type);
  const PreviewComponent = registeredComp?.preview;
  
  // 디자인 모드: 실제 컴포넌트 또는 미리보기 표시 (헤더 없음 - 뷰어와 동일하게)
  if (isDesignMode) {
    const ActualComp = registeredComp?.component;
    
    // 실제 컴포넌트가 등록되어 있으면 실제 데이터로 렌더링 (대시보드 등)
    if (ActualComp) {
      // 아이콘 컴포넌트는 클릭 이벤트가 필요하므로 pointer-events 허용
      // CardList 컴포넌트도 버튼 클릭이 필요하므로 pointer-events 허용
      const needsPointerEvents = component.type === "pop-icon" || component.type === "pop-card-list" || component.type === "pop-card-list-v2";
      
      return (
        <div className={cn(
          "h-full w-full overflow-hidden",
          !needsPointerEvents && "pointer-events-none"
        )}>
          <ActualComp 
            config={component.config} 
            label={component.label}
            isDesignMode={isDesignMode}
            previewPageIndex={previewPageIndex}
            componentId={component.id}
            screenId={screenId}
            currentRowSpan={effectivePosition.rowSpan}
            currentColSpan={effectivePosition.colSpan}
            onRequestResize={onRequestResize}
          />
        </div>
      );
    }
    
    // 미등록: preview 컴포넌트 또는 기본 플레이스홀더
    return (
      <div className="flex h-full w-full items-center justify-center overflow-hidden">
        {PreviewComponent ? (
          <PreviewComponent config={component.config} />
        ) : (
          <span className="text-xs text-muted-foreground/70 p-2">
            {typeLabel}
          </span>
        )}
      </div>
    );
  }
  
  // 실제 모드: 컴포넌트 렌더링 (뷰어 모드에서도 리사이즈 지원)
  return renderActualComponent(component, effectivePosition, onRequestResize, screenId);
}

// ========================================
// 실제 컴포넌트 렌더링 (뷰어 모드)
// ========================================

function renderActualComponent(
  component: PopComponentDefinition,
  effectivePosition?: PopGridPosition,
  onRequestResize?: (componentId: string, newRowSpan: number, newColSpan?: number) => void,
  screenId?: string,
): React.ReactNode {
  // 레지스트리에서 등록된 실제 컴포넌트 조회
  const registeredComp = PopComponentRegistry.getComponent(component.type);
  const ActualComp = registeredComp?.component;

  if (ActualComp) {
    return (
      <div className="h-full w-full overflow-hidden">
        <ActualComp 
          config={component.config} 
          label={component.label}
          componentId={component.id}
          screenId={screenId}
          currentRowSpan={effectivePosition?.rowSpan}
          currentColSpan={effectivePosition?.colSpan}
          onRequestResize={onRequestResize}
        />
      </div>
    );
  }

  // 미등록 컴포넌트: 플레이스홀더 (fallback)
  const typeLabel = COMPONENT_TYPE_LABELS[component.type] || component.type;
  return (
    <div className="flex h-full w-full items-center justify-center p-2">
      <span className="text-xs text-muted-foreground">{component.label || typeLabel}</span>
    </div>
  );
}
