// POP 그리드 유틸리티 (리플로우, 겹침 해결, 위치 계산)

import { 
  PopGridPosition, 
  GridMode, 
  GRID_BREAKPOINTS,
  PopLayoutData,
} from "../types/pop-layout";

// ========================================
// 리플로우 (행 그룹 기반 자동 재배치)
// ========================================

/**
 * 행 그룹 리플로우
 *
 * CSS Flexbox wrap 원리로 자동 재배치한다.
 * 1. 같은 행의 컴포넌트를 한 묶음으로 처리
 * 2. 최소 2x2칸 보장 (터치 가능한 최소 크기)
 * 3. 한 줄에 안 들어가면 다음 줄로 줄바꿈 (숨김 없음)
 * 4. 설계 너비의 50% 이상인 컴포넌트는 전체 너비 확장
 * 5. 리플로우 후 겹침 해결
 */
export function convertAndResolvePositions(
  components: Array<{ id: string; position: PopGridPosition }>,
  targetMode: GridMode
): Array<{ id: string; position: PopGridPosition }> {
  if (components.length === 0) return [];
  
  const targetColumns = GRID_BREAKPOINTS[targetMode].columns;
  const designColumns = GRID_BREAKPOINTS["tablet_landscape"].columns;
  
  if (targetColumns >= designColumns) {
    return components.map(c => ({ id: c.id, position: { ...c.position } }));
  }
  
  const ratio = targetColumns / designColumns;
  const MIN_COL_SPAN = 2;
  const MIN_ROW_SPAN = 2;
  
  const rowGroups: Record<number, Array<{ id: string; position: PopGridPosition }>> = {};
  components.forEach(comp => {
    const r = comp.position.row;
    if (!rowGroups[r]) rowGroups[r] = [];
    rowGroups[r].push(comp);
  });
  
  const placed: Array<{ id: string; position: PopGridPosition }> = [];
  let outputRow = 1;
  
  const sortedRows = Object.keys(rowGroups).map(Number).sort((a, b) => a - b);
  
  for (const rowKey of sortedRows) {
    const group = rowGroups[rowKey].sort((a, b) => a.position.col - b.position.col);
    let currentCol = 1;
    let maxRowSpanInLine = 0;
    
    for (const comp of group) {
      const pos = comp.position;
      const isMainContent = pos.colSpan >= designColumns * 0.5;
      
      let scaledSpan = isMainContent
        ? targetColumns
        : Math.max(MIN_COL_SPAN, Math.round(pos.colSpan * ratio));
      scaledSpan = Math.min(scaledSpan, targetColumns);
      
      const scaledRowSpan = Math.max(MIN_ROW_SPAN, pos.rowSpan);
      
      if (currentCol + scaledSpan - 1 > targetColumns) {
        outputRow += Math.max(1, maxRowSpanInLine);
        currentCol = 1;
        maxRowSpanInLine = 0;
      }
      
      placed.push({
        id: comp.id,
        position: {
          col: currentCol,
          row: outputRow,
          colSpan: scaledSpan,
          rowSpan: scaledRowSpan,
        },
      });
      
      maxRowSpanInLine = Math.max(maxRowSpanInLine, scaledRowSpan);
      currentCol += scaledSpan;
    }
    
    outputRow += Math.max(1, maxRowSpanInLine);
  }
  
  return resolveOverlaps(placed, targetColumns);
}

// ========================================
// 겹침 감지 및 해결
// ========================================

export function isOverlapping(a: PopGridPosition, b: PopGridPosition): boolean {
  const aColEnd = a.col + a.colSpan - 1;
  const bColEnd = b.col + b.colSpan - 1;
  const colOverlap = !(aColEnd < b.col || bColEnd < a.col);
  
  const aRowEnd = a.row + a.rowSpan - 1;
  const bRowEnd = b.row + b.rowSpan - 1;
  const rowOverlap = !(aRowEnd < b.row || bRowEnd < a.row);
  
  return colOverlap && rowOverlap;
}

export function resolveOverlaps(
  positions: Array<{ id: string; position: PopGridPosition }>,
  columns: number
): Array<{ id: string; position: PopGridPosition }> {
  const sorted = [...positions].sort((a, b) => 
    a.position.row - b.position.row || a.position.col - b.position.col
  );
  
  const resolved: Array<{ id: string; position: PopGridPosition }> = [];
  
  sorted.forEach((item) => {
    let { row, col, colSpan, rowSpan } = item.position;
    
    if (col + colSpan - 1 > columns) {
      colSpan = columns - col + 1;
    }
    
    let attempts = 0;
    while (attempts < 100) {
      const currentPos: PopGridPosition = { col, row, colSpan, rowSpan };
      const hasOverlap = resolved.some(r => isOverlapping(currentPos, r.position));
      if (!hasOverlap) break;
      row++;
      attempts++;
    }
    
    resolved.push({
      id: item.id,
      position: { col, row, colSpan, rowSpan },
    });
  });
  
  return resolved;
}

// ========================================
// 자동 배치 (새 컴포넌트 드롭 시)
// ========================================

export function findNextEmptyPosition(
  existingPositions: PopGridPosition[],
  colSpan: number,
  rowSpan: number,
  columns: number
): PopGridPosition {
  let row = 1;
  let col = 1;
  let attempts = 0;
  
  while (attempts < 1000) {
    const candidatePos: PopGridPosition = { col, row, colSpan, rowSpan };
    
    if (col + colSpan - 1 > columns) {
      col = 1;
      row++;
      continue;
    }
    
    const hasOverlap = existingPositions.some(pos => isOverlapping(candidatePos, pos));
    if (!hasOverlap) return candidatePos;
    
    col++;
    if (col + colSpan - 1 > columns) {
      col = 1;
      row++;
    }
    attempts++;
  }
  
  return { col: 1, row: row + 1, colSpan, rowSpan };
}

// ========================================
// 유효 위치 계산
// ========================================

/**
 * 컴포넌트의 유효 위치를 계산한다.
 * 우선순위: 1. 오버라이드 → 2. 자동 재배치 → 3. 원본 위치
 */
function getEffectiveComponentPosition(
  componentId: string,
  layout: PopLayoutData,
  mode: GridMode,
  autoResolvedPositions?: Array<{ id: string; position: PopGridPosition }>
): PopGridPosition | null {
  const component = layout.components[componentId];
  if (!component) return null;
  
  const override = layout.overrides?.[mode]?.positions?.[componentId];
  if (override) {
    return { ...component.position, ...override };
  }
  
  if (autoResolvedPositions) {
    const autoResolved = autoResolvedPositions.find(p => p.id === componentId);
    if (autoResolved) return autoResolved.position;
  } else {
    const componentsArray = Object.entries(layout.components).map(([id, comp]) => ({
      id,
      position: comp.position,
    }));
    const resolved = convertAndResolvePositions(componentsArray, mode);
    const autoResolved = resolved.find(p => p.id === componentId);
    if (autoResolved) return autoResolved.position;
  }
  
  return component.position;
}

/**
 * 모든 컴포넌트의 유효 위치를 일괄 계산한다.
 * 숨김 처리된 컴포넌트는 제외.
 */
export function getAllEffectivePositions(
  layout: PopLayoutData,
  mode: GridMode
): Map<string, PopGridPosition> {
  const result = new Map<string, PopGridPosition>();
  
  const hiddenIds = layout.overrides?.[mode]?.hidden || [];
  
  const componentsArray = Object.entries(layout.components).map(([id, comp]) => ({
    id,
    position: comp.position,
  }));
  const autoResolvedPositions = convertAndResolvePositions(componentsArray, mode);
  
  Object.keys(layout.components).forEach(componentId => {
    if (hiddenIds.includes(componentId)) return;
    
    const position = getEffectiveComponentPosition(
      componentId, layout, mode, autoResolvedPositions
    );
    
    if (position) {
      result.set(componentId, position);
    }
  });
  
  return result;
}
