"use client";

import React from "react";
import { ComponentData, WebType, WidgetComponent } from "@/types/screen";
import { DynamicComponentRenderer } from "@/lib/registry/DynamicComponentRenderer";
import {
  Database,
  Type,
  Hash,
  List,
  AlignLeft,
  CheckSquare,
  Radio,
  Calendar,
  Code,
  Building,
  File,
} from "lucide-react";

// 컴포넌트 렌더러들 자동 등록
import "@/lib/registry/components";

interface RealtimePreviewProps {
  component: ComponentData;
  isSelected?: boolean;
  isDesignMode?: boolean; // 편집 모드 여부
  onClick?: (e?: React.MouseEvent) => void;
  onDoubleClick?: (e?: React.MouseEvent) => void; // 더블클릭 핸들러 추가
  onDragStart?: (e: React.DragEvent) => void;
  onDragEnd?: () => void;
  onGroupToggle?: (groupId: string) => void; // 그룹 접기/펼치기
  children?: React.ReactNode; // 그룹 내 자식 컴포넌트들
  selectedScreen?: any;
  onZoneComponentDrop?: (e: React.DragEvent, zoneId: string, layoutId: string) => void; // 존별 드롭 핸들러
  onZoneClick?: (zoneId: string) => void; // 존 클릭 핸들러
  onConfigChange?: (config: any) => void; // 설정 변경 핸들러

  // 버튼 액션을 위한 props
  screenId?: number;
  tableName?: string;
  userId?: string; // 🆕 현재 사용자 ID
  userName?: string; // 🆕 현재 사용자 이름
  companyCode?: string; // 🆕 현재 사용자의 회사 코드
  menuObjid?: number; // 🆕 현재 메뉴 OBJID (메뉴 스코프)
  selectedRowsData?: any[];
  onSelectedRowsChange?: (selectedRows: any[], selectedRowsData: any[]) => void;
  flowSelectedData?: any[];
  flowSelectedStepId?: number | null;
  onFlowSelectedDataChange?: (selectedData: any[], stepId: number | null) => void;
  refreshKey?: number;
  onRefresh?: () => void;
  flowRefreshKey?: number;
  onFlowRefresh?: () => void;

  // 폼 데이터 관련 props
  formData?: Record<string, any>;
  onFormDataChange?: (fieldName: string, value: any) => void;

  // 테이블 정렬 정보
  sortBy?: string;
  sortOrder?: "asc" | "desc";
  columnOrder?: string[];
}

// 동적 위젯 타입 아이콘 (레지스트리에서 조회)
const getWidgetIcon = (widgetType: WebType | undefined): React.ReactNode => {
  if (!widgetType) return <Type className="h-3 w-3" />;

  const iconMap: Record<string, React.ReactNode> = {
    text: <span className="text-xs">Aa</span>,
    number: <Hash className="h-3 w-3" />,
    decimal: <Hash className="h-3 w-3" />,
    date: <Calendar className="h-3 w-3" />,
    datetime: <Calendar className="h-3 w-3" />,
    select: <List className="h-3 w-3" />,
    dropdown: <List className="h-3 w-3" />,
    textarea: <AlignLeft className="h-3 w-3" />,
    boolean: <CheckSquare className="h-3 w-3" />,
    checkbox: <CheckSquare className="h-3 w-3" />,
    radio: <Radio className="h-3 w-3" />,
    code: <Code className="h-3 w-3" />,
    entity: <Building className="h-3 w-3" />,
    file: <File className="h-3 w-3" />,
    email: <span className="text-xs">@</span>,
    tel: <span className="text-xs">☎</span>,
    button: <span className="text-xs">BTN</span>,
  };

  return iconMap[widgetType] || <Type className="h-3 w-3" />;
};

export const RealtimePreviewDynamic: React.FC<RealtimePreviewProps> = ({
  component,
  isSelected = false,
  isDesignMode = true, // 기본값은 편집 모드
  onClick,
  onDoubleClick,
  onDragStart,
  onDragEnd,
  onGroupToggle,
  children,
  selectedScreen,
  onZoneComponentDrop,
  onZoneClick,
  onConfigChange,
  screenId,
  tableName,
  userId, // 🆕 사용자 ID
  userName, // 🆕 사용자 이름
  companyCode, // 🆕 회사 코드
  menuObjid, // 🆕 메뉴 OBJID
  selectedRowsData,
  onSelectedRowsChange,
  flowSelectedData,
  flowSelectedStepId,
  onFlowSelectedDataChange,
  refreshKey,
  onRefresh,
  sortBy,
  sortOrder,
  columnOrder,
  flowRefreshKey,
  onFlowRefresh,
  formData,
  onFormDataChange,
}) => {
  const [actualHeight, setActualHeight] = React.useState<number | null>(null);
  const contentRef = React.useRef<HTMLDivElement>(null);
  const lastUpdatedHeight = React.useRef<number | null>(null);

  // 플로우 위젯의 실제 높이 측정
  React.useEffect(() => {
    const isFlowWidget = component.type === "component" && (component as any).componentType === "flow-widget";

    if (isFlowWidget && contentRef.current) {
      const measureHeight = () => {
        if (contentRef.current) {
          // getBoundingClientRect()로 실제 렌더링된 높이 측정
          const rect = contentRef.current.getBoundingClientRect();
          const measured = rect.height;

          // scrollHeight도 함께 확인하여 더 큰 값 사용
          const scrollHeight = contentRef.current.scrollHeight;
          const rawHeight = Math.max(measured, scrollHeight);

          // 40px 단위로 올림
          const finalHeight = Math.ceil(rawHeight / 40) * 40;

          if (finalHeight > 0 && Math.abs(finalHeight - (actualHeight || 0)) > 10) {
            setActualHeight(finalHeight);

            // 컴포넌트의 실제 size.height도 업데이트 (중복 업데이트 방지)
            if (onConfigChange && finalHeight !== lastUpdatedHeight.current && finalHeight !== component.size?.height) {
              lastUpdatedHeight.current = finalHeight;
              // size는 별도 속성이므로 직접 업데이트
              const event = new CustomEvent("updateComponentSize", {
                detail: {
                  componentId: component.id,
                  height: finalHeight,
                },
              });
              window.dispatchEvent(event);
            }
          }
        }
      };

      // 초기 측정 (렌더링 완료 후)
      const initialTimer = setTimeout(() => {
        measureHeight();
      }, 100);

      // 추가 측정 (데이터 로딩 완료 대기)
      const delayedTimer = setTimeout(() => {
        measureHeight();
      }, 500);

      // 스텝 클릭 등으로 높이가 변경될 때를 위한 추가 측정
      const extendedTimer = setTimeout(() => {
        measureHeight();
      }, 1000);

      // ResizeObserver로 크기 변화 감지 (스텝 클릭 시 데이터 테이블 펼쳐짐)
      const resizeObserver = new ResizeObserver(() => {
        // 약간의 지연을 두고 측정 (DOM 업데이트 완료 대기)
        setTimeout(() => {
          measureHeight();
        }, 100);
      });

      resizeObserver.observe(contentRef.current);

      return () => {
        clearTimeout(initialTimer);
        clearTimeout(delayedTimer);
        clearTimeout(extendedTimer);
        resizeObserver.disconnect();
      };
    }
  }, [component.type, component.id, actualHeight, component.size?.height, onConfigChange]);
  const { id, type, position, size, style: componentStyle } = component;

  // 선택 상태에 따른 스타일 (z-index 낮춤 - 패널과 모달보다 아래)
  const selectionStyle = isSelected
    ? {
        outline: "2px solid rgb(59, 130, 246)",
        outlineOffset: "0px", // 스크롤 방지를 위해 0으로 설정
        zIndex: 20,
      }
    : {};

  // 컴포넌트 기본 스타일 - 레이아웃은 항상 맨 아래
  // 🔥 모든 컴포넌트를 픽셀 기준으로 통일 (스케일로만 조정)
  const getWidth = () => {
    // table-list는 화면 너비 전체 사용
    if (component.componentConfig?.type === "table-list") {
      // 디자인 해상도 기준으로 픽셀 반환
      const screenWidth = 1920; // 기본 디자인 해상도
      return `${screenWidth}px`;
    }

    // 모든 컴포넌트는 size.width 픽셀 사용
    const width = `${size?.width || 100}px`;
    return width;
  };

  const getHeight = () => {
    // 플로우 위젯의 경우 측정된 높이 사용
    const isFlowWidget = component.type === "component" && (component as any).componentType === "flow-widget";
    if (isFlowWidget && actualHeight) {
      return `${actualHeight}px`;
    }

    // 1순위: style.height가 있으면 우선 사용 (문자열 그대로 또는 숫자+px)
    if (componentStyle?.height) {
      return typeof componentStyle.height === "number" ? `${componentStyle.height}px` : componentStyle.height;
    }

    // 2순위: size.height (픽셀)
    if (component.componentConfig?.type === "table-list") {
      return `${Math.max(size?.height || 200, 200)}px`;
    }

    // size.height가 있으면 그대로 사용, 없으면 최소 10px
    return `${size?.height || 10}px`;
  };

  // layout 타입 컴포넌트인지 확인
  const isLayoutComponent = component.type === "layout" || (component.componentConfig as any)?.type?.includes("layout");

  // layout 컴포넌트는 component 객체에 style.height 추가
  const enhancedComponent = isLayoutComponent
    ? {
        ...component,
        style: {
          ...component.style,
          height: getHeight(),
        },
      }
    : component;

  // componentStyle에서 width, height 제거 (size.width, size.height만 사용)
  const { width: _styleWidth, height: _styleHeight, ...restComponentStyle } = componentStyle || {};
  
  const baseStyle = {
    left: `${position.x}px`,
    top: `${position.y}px`,
    ...restComponentStyle, // width/height 제외한 스타일 먼저 적용
    width: getWidth(), // size.width로 덮어쓰기
    height: getHeight(), // size.height로 덮어쓰기
    zIndex: component.type === "layout" ? 1 : position.z || 2,
    right: undefined,
  };

  // 🔍 DOM 렌더링 후 실제 크기 측정
  const innerDivRef = React.useRef<HTMLDivElement>(null);
  const outerDivRef = React.useRef<HTMLDivElement>(null);

  React.useEffect(() => {
    if (outerDivRef.current && innerDivRef.current) {
      const outerRect = outerDivRef.current.getBoundingClientRect();
      const innerRect = innerDivRef.current.getBoundingClientRect();
      // 크기 측정 완료
    }
  }, [id, component.label, (component as any).gridColumns, baseStyle.width]);

  const handleClick = (e: React.MouseEvent) => {
    e.stopPropagation();
    onClick?.(e);
  };

  const handleDoubleClick = (e: React.MouseEvent) => {
    e.stopPropagation();
    onDoubleClick?.(e);
  };

  const handleDragStart = (e: React.DragEvent) => {
    e.stopPropagation();
    onDragStart?.(e);
  };

  const handleDragEnd = () => {
    onDragEnd?.();
  };

  return (
    <div
      ref={outerDivRef}
      id={`component-${id}`}
      data-component-id={id}
      className="absolute cursor-pointer transition-all duration-200 ease-out"
      style={{ ...baseStyle, ...selectionStyle }}
      onClick={handleClick}
      onDoubleClick={handleDoubleClick}
      draggable={isDesignMode} // 디자인 모드에서만 드래그 가능
      onDragStart={isDesignMode ? handleDragStart : undefined}
      onDragEnd={isDesignMode ? handleDragEnd : undefined}
    >
      {/* 동적 컴포넌트 렌더링 */}
      <div
        ref={(node) => {
          // 멀티 ref 처리
          innerDivRef.current = node;
          if (component.type === "component" && (component as any).componentType === "flow-widget") {
            (contentRef as any).current = node;
          }
        }}
        className={`${component.type === "component" && (component as any).componentType === "flow-widget" ? "h-auto" : "h-full"} overflow-visible`}
        style={{ width: "100%", maxWidth: "100%" }}
      >
        <DynamicComponentRenderer
          component={enhancedComponent}
          isSelected={isSelected}
          isDesignMode={isDesignMode}
          isInteractive={!isDesignMode} // 편집 모드가 아닐 때만 인터랙티브
          onClick={onClick}
          onDragStart={onDragStart}
          onDragEnd={onDragEnd}
          children={children}
          selectedScreen={selectedScreen}
          onZoneComponentDrop={onZoneComponentDrop}
          onZoneClick={onZoneClick}
          onConfigChange={onConfigChange}
          screenId={screenId}
          tableName={tableName}
          userId={userId}
          userName={userName}
          companyCode={companyCode}
          menuObjid={menuObjid}
          selectedRowsData={selectedRowsData}
          onSelectedRowsChange={onSelectedRowsChange}
          flowSelectedData={flowSelectedData}
          flowSelectedStepId={flowSelectedStepId}
          onFlowSelectedDataChange={onFlowSelectedDataChange}
          refreshKey={refreshKey}
          onRefresh={onRefresh}
          flowRefreshKey={flowRefreshKey}
          onFlowRefresh={onFlowRefresh}
          formData={formData}
          onFormDataChange={onFormDataChange}
          sortBy={sortBy}
          sortOrder={sortOrder}
          columnOrder={columnOrder}
        />
      </div>

      {/* 선택된 컴포넌트 정보 표시 */}
      {isSelected && (
        <div className="bg-primary text-primary-foreground absolute -top-7 left-0 rounded-md px-2.5 py-1 text-xs font-medium shadow-sm">
          {type === "widget" && (
            <div className="flex items-center gap-1.5">
              {getWidgetIcon((component as WidgetComponent).widgetType)}
              <span>{(component as WidgetComponent).widgetType || "widget"}</span>
            </div>
          )}
          {type !== "widget" && (
            <div className="flex items-center gap-1.5">
              <span>{component.componentConfig?.type || type}</span>
            </div>
          )}
        </div>
      )}
    </div>
  );
};

// 기존 RealtimePreview와의 호환성을 위한 export
export { RealtimePreviewDynamic as RealtimePreview };
export default RealtimePreviewDynamic;
