import { Position, Size } from "@/types/screen";
import { GridSettings } from "@/types/screen-management";

export interface GridInfo {
  columnWidth: number;
  totalWidth: number;
  totalHeight: number;
}

/**
 * 격자 정보 계산
 */
export function calculateGridInfo(
  containerWidth: number,
  containerHeight: number,
  gridSettings: GridSettings,
): GridInfo {
  const { gap, padding } = gridSettings;
  let { columns } = gridSettings;

  // 🔥 최소 컬럼 너비를 보장하기 위한 최대 컬럼 수 계산
  const MIN_COLUMN_WIDTH = 30; // 최소 컬럼 너비 30px
  const availableWidth = containerWidth - padding * 2;
  const maxPossibleColumns = Math.floor((availableWidth + gap) / (MIN_COLUMN_WIDTH + gap));
  
  // 설정된 컬럼 수가 너무 많으면 자동으로 제한
  if (columns > maxPossibleColumns) {
    console.warn(
      `⚠️ 격자 컬럼 수가 너무 많습니다. ${columns}개 → ${maxPossibleColumns}개로 자동 조정됨 (최소 컬럼 너비: ${MIN_COLUMN_WIDTH}px)`,
    );
    columns = Math.max(1, maxPossibleColumns);
  }

  // 격자 간격을 고려한 컬럼 너비 계산
  const totalGaps = (columns - 1) * gap;
  const columnWidth = (availableWidth - totalGaps) / columns;

  return {
    columnWidth: Math.max(columnWidth, MIN_COLUMN_WIDTH),
    totalWidth: containerWidth,
    totalHeight: containerHeight,
  };
}

/**
 * 위치를 격자에 맞춤
 */
export function snapToGrid(position: Position, gridInfo: GridInfo, gridSettings: GridSettings): Position {
  if (!gridSettings.snapToGrid) {
    return position;
  }

  const { columnWidth } = gridInfo;
  const { gap, padding } = gridSettings;

  // 격자 셀 크기 (컬럼 너비 + 간격을 하나의 격자 단위로 계산)
  const cellWidth = columnWidth + gap;
  const cellHeight = 10; // 행 높이 10px 단위로 고정

  // 패딩을 제외한 상대 위치
  const relativeX = position.x - padding;
  const relativeY = position.y - padding;

  // 격자 기준으로 위치 계산 (가장 가까운 격자점으로 스냅)
  const gridX = Math.round(relativeX / cellWidth);
  const gridY = Math.round(relativeY / cellHeight);

  // 실제 픽셀 위치로 변환
  const snappedX = Math.max(padding, padding + gridX * cellWidth);
  const snappedY = Math.max(padding, padding + gridY * cellHeight);

  return {
    x: snappedX,
    y: snappedY,
    z: position.z,
  };
}

/**
 * 크기를 격자에 맞춤
 */
export function snapSizeToGrid(size: Size, gridInfo: GridInfo, gridSettings: GridSettings): Size {
  if (!gridSettings.snapToGrid) {
    return size;
  }

  const { columnWidth } = gridInfo;
  const { gap } = gridSettings;

  // 격자 단위로 너비 계산
  // 컴포넌트가 차지하는 컬럼 수를 올바르게 계산
  let gridColumns = 1;

  // 현재 너비에서 가장 가까운 격자 컬럼 수 찾기
  for (let cols = 1; cols <= gridSettings.columns; cols++) {
    const targetWidth = cols * columnWidth + (cols - 1) * gap;
    if (size.width <= targetWidth + (columnWidth + gap) / 2) {
      gridColumns = cols;
      break;
    }
    gridColumns = cols;
  }

  const snappedWidth = gridColumns * columnWidth + (gridColumns - 1) * gap;

  // 높이는 10px 단위로 스냅
  const rowHeight = 10;
  const snappedHeight = Math.max(10, Math.round(size.height / rowHeight) * rowHeight);

  // console.log(
  //   `📏 크기 스냅: ${size.width}px → ${snappedWidth}px (${gridColumns}컬럼, 컬럼너비:${columnWidth}px, 간격:${gap}px)`,
  // );

  return {
    width: Math.max(columnWidth, snappedWidth),
    height: snappedHeight,
  };
}

/**
 * 격자 컬럼 수로 너비 계산
 */
export function calculateWidthFromColumns(columns: number, gridInfo: GridInfo, gridSettings: GridSettings): number {
  const { columnWidth } = gridInfo;
  const { gap } = gridSettings;

  return columns * columnWidth + (columns - 1) * gap;
}

/**
 * gridColumns 속성을 기반으로 컴포넌트 크기 업데이트
 */
export function updateSizeFromGridColumns(
  component: { gridColumns?: number; size: Size },
  gridInfo: GridInfo,
  gridSettings: GridSettings,
): Size {
  if (!component.gridColumns || component.gridColumns < 1) {
    return component.size;
  }

  const newWidth = calculateWidthFromColumns(component.gridColumns, gridInfo, gridSettings);

  return {
    width: newWidth,
    height: component.size.height, // 높이는 유지
  };
}

/**
 * 컴포넌트의 gridColumns를 자동으로 크기에 맞게 조정
 */
export function adjustGridColumnsFromSize(
  component: { size: Size },
  gridInfo: GridInfo,
  gridSettings: GridSettings,
): number {
  const columns = calculateColumnsFromWidth(component.size.width, gridInfo, gridSettings);
  return Math.min(Math.max(1, columns), gridSettings.columns); // 1-12 범위로 제한
}

/**
 * 너비에서 격자 컬럼 수 계산
 */
export function calculateColumnsFromWidth(width: number, gridInfo: GridInfo, gridSettings: GridSettings): number {
  const { columnWidth } = gridInfo;
  const { gap } = gridSettings;

  return Math.max(1, Math.round((width + gap) / (columnWidth + gap)));
}

/**
 * 격자 가이드라인 생성
 */
export function generateGridLines(
  containerWidth: number,
  containerHeight: number,
  gridSettings: GridSettings,
): {
  verticalLines: number[];
  horizontalLines: number[];
} {
  const { columns, gap, padding } = gridSettings;
  const gridInfo = calculateGridInfo(containerWidth, containerHeight, gridSettings);
  const { columnWidth } = gridInfo;

  // 격자 셀 크기 (스냅 로직과 동일하게)
  const cellWidth = columnWidth + gap;
  const cellHeight = 10; // 행 높이 10px 단위로 고정

  // 세로 격자선
  const verticalLines: number[] = [];
  for (let i = 0; i <= columns; i++) {
    const x = padding + i * cellWidth;
    if (x <= containerWidth) {
      verticalLines.push(x);
    }
  }

  // 가로 격자선
  const horizontalLines: number[] = [];
  for (let y = padding; y < containerHeight; y += cellHeight) {
    horizontalLines.push(y);
  }

  return {
    verticalLines,
    horizontalLines,
  };
}

/**
 * 컴포넌트가 격자 경계에 있는지 확인
 */
export function isOnGridBoundary(
  position: Position,
  size: Size,
  gridInfo: GridInfo,
  gridSettings: GridSettings,
  tolerance: number = 5,
): boolean {
  const snappedPos = snapToGrid(position, gridInfo, gridSettings);
  const snappedSize = snapSizeToGrid(size, gridInfo, gridSettings);

  const positionMatch =
    Math.abs(position.x - snappedPos.x) <= tolerance && Math.abs(position.y - snappedPos.y) <= tolerance;

  const sizeMatch =
    Math.abs(size.width - snappedSize.width) <= tolerance && Math.abs(size.height - snappedSize.height) <= tolerance;

  return positionMatch && sizeMatch;
}

/**
 * 그룹 내부 컴포넌트들을 격자에 맞게 정렬
 */
export function alignGroupChildrenToGrid(
  children: any[],
  groupPosition: Position,
  gridInfo: GridInfo,
  gridSettings: GridSettings,
): any[] {
  if (!gridSettings.snapToGrid || children.length === 0) return children;

  console.log("🔧 alignGroupChildrenToGrid 시작:", {
    childrenCount: children.length,
    groupPosition,
    gridInfo,
    gridSettings,
  });

  return children.map((child, index) => {
    console.log(`📐 자식 ${index + 1} 처리 중:`, {
      childId: child.id,
      originalPosition: child.position,
      originalSize: child.size,
    });

    const { columnWidth } = gridInfo;
    const { gap } = gridSettings;

    // 그룹 내부 패딩 고려한 격자 정렬
    const padding = 16;
    const effectiveX = child.position.x - padding;
    const columnIndex = Math.round(effectiveX / (columnWidth + gap));
    const snappedX = padding + columnIndex * (columnWidth + gap);

    // Y 좌표는 10px 단위로 스냅
    const rowHeight = 10;
    const effectiveY = child.position.y - padding;
    const rowIndex = Math.round(effectiveY / rowHeight);
    const snappedY = padding + rowIndex * rowHeight;

    // 크기는 외부 격자와 동일하게 스냅 (columnWidth + gap 사용)
    const fullColumnWidth = columnWidth + gap; // 외부 격자와 동일한 크기
    const widthInColumns = Math.max(1, Math.round(child.size.width / fullColumnWidth));
    const snappedWidth = widthInColumns * fullColumnWidth - gap; // gap 제거하여 실제 컴포넌트 크기
    const snappedHeight = Math.max(10, Math.round(child.size.height / rowHeight) * rowHeight);

    const snappedChild = {
      ...child,
      position: {
        x: Math.max(padding, snappedX), // 패딩만큼 최소 여백 확보
        y: Math.max(padding, snappedY),
        z: child.position.z || 1,
      },
      size: {
        width: snappedWidth,
        height: snappedHeight,
      },
    };

    console.log(`✅ 자식 ${index + 1} 격자 정렬 완료:`, {
      childId: child.id,
      calculation: {
        effectiveX,
        effectiveY,
        columnIndex,
        rowIndex,
        widthInColumns,
        originalX: child.position.x,
        snappedX: snappedChild.position.x,
        padding,
      },
      snappedPosition: snappedChild.position,
      snappedSize: snappedChild.size,
      deltaX: snappedChild.position.x - child.position.x,
      deltaY: snappedChild.position.y - child.position.y,
    });

    return snappedChild;
  });
}

/**
 * 그룹 생성 시 최적화된 그룹 크기 계산
 */
export function calculateOptimalGroupSize(
  children: Array<{ position: Position; size: Size }>,
  gridInfo: GridInfo,
  gridSettings: GridSettings,
): Size {
  if (children.length === 0) {
    return { width: gridInfo.columnWidth * 2, height: 10 * 4 };
  }

  console.log("📏 calculateOptimalGroupSize 시작:", {
    childrenCount: children.length,
    children: children.map((c) => ({ pos: c.position, size: c.size })),
  });

  // 모든 자식 컴포넌트를 포함하는 최소 경계 계산
  const bounds = children.reduce(
    (acc, child) => ({
      minX: Math.min(acc.minX, child.position.x),
      minY: Math.min(acc.minY, child.position.y),
      maxX: Math.max(acc.maxX, child.position.x + child.size.width),
      maxY: Math.max(acc.maxY, child.position.y + child.size.height),
    }),
    { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity },
  );

  console.log("📐 경계 계산:", bounds);

  const contentWidth = bounds.maxX - bounds.minX;
  const contentHeight = bounds.maxY - bounds.minY;

  // 그룹은 격자 스냅 없이 컨텐츠에 맞는 자연스러운 크기
  const padding = 16; // 그룹 내부 여백
  const groupSize = {
    width: contentWidth + padding * 2,
    height: contentHeight + padding * 2,
  };

  console.log("✅ 자연스러운 그룹 크기:", {
    contentSize: { width: contentWidth, height: contentHeight },
    withPadding: groupSize,
    strategy: "그룹은 격자 스냅 없이, 내부 컴포넌트만 격자에 맞춤",
  });

  return groupSize;
}

/**
 * 그룹 내 상대 좌표를 격자 기준으로 정규화
 */
export function normalizeGroupChildPositions(children: any[], gridSettings: GridSettings): any[] {
  if (!gridSettings.snapToGrid || children.length === 0) return children;

  console.log("🔄 normalizeGroupChildPositions 시작:", {
    childrenCount: children.length,
    originalPositions: children.map((c) => ({ id: c.id, pos: c.position })),
  });

  // 모든 자식의 최소 위치 찾기
  const minX = Math.min(...children.map((child) => child.position.x));
  const minY = Math.min(...children.map((child) => child.position.y));

  console.log("📍 최소 위치:", { minX, minY });

  // 그룹 내에서 시작점을 패딩만큼 떨어뜨림 (자연스러운 여백)
  const padding = 16;
  const startX = padding;
  const startY = padding;

  const normalizedChildren = children.map((child) => ({
    ...child,
    position: {
      x: child.position.x - minX + startX,
      y: child.position.y - minY + startY,
      z: child.position.z || 1,
    },
  }));

  console.log("✅ 정규화 완료:", {
    normalizedPositions: normalizedChildren.map((c) => ({ id: c.id, pos: c.position })),
  });

  return normalizedChildren;
}
