import type { FurnitureItem } from '@house-plan-maker/shared';
import { rotatedAnchorOffsetToCenter } from '@house-plan-maker/shared';

/**
 * Axis-aligned bounding box for a furniture item, in world (room) coordinates.
 *
 * Per the project rule "rotation only affects visuals and hitbox, positioning
 * always uses the initial coordinate system", collision detection — which is
 * a positional concern — operates on the UNROTATED rectangle. A rotated bed
 * is treated as if it were axis-aligned for the purpose of overlap testing.
 */
interface AABB {
  readonly id: string;
  readonly minX: number;
  readonly minY: number;
  readonly maxX: number;
  readonly maxY: number;
  readonly bottom: number;
  readonly top: number;
}

function computeAabb(item: FurnitureItem): AABB {
  // Center is rotation-aware via the anchor helper. The AABB itself is
  // still the unrotated `width × depth` rectangle (per the project rule
  // that positioning math uses the unrotated extents), but its position
  // tracks the rotated anchor offset.
  const offset = rotatedAnchorOffsetToCenter(
    item.positionAnchor,
    item.width,
    item.depth,
    item.rotation,
  );
  const cx = item.x + offset.dx;
  const cy = item.y + offset.dy;
  const halfW = item.width / 2;
  const halfD = item.depth / 2;
  return {
    id: item.id,
    minX: cx - halfW,
    minY: cy - halfD,
    maxX: cx + halfW,
    maxY: cy + halfD,
    bottom: item.elevationFromFloor,
    top: item.elevationFromFloor + item.height,
  };
}

function aabbOverlap(a: AABB, b: AABB): boolean {
  if (a.maxX <= b.minX || b.maxX <= a.minX) return false;
  if (a.maxY <= b.minY || b.maxY <= a.minY) return false;
  if (a.top <= b.bottom || b.top <= a.bottom) return false;
  return true;
}

/**
 * Find all furniture IDs that collide. Uses unrotated axis-aligned bounding
 * boxes — see the AABB doc comment for the rationale.
 */
export function findCollidingFurniture(
  items: readonly FurnitureItem[],
): ReadonlySet<string> {
  if (items.length < 2) return new Set();

  const boxes = items.map(computeAabb);
  const colliding = new Set<string>();

  for (let i = 0; i < boxes.length; i++) {
    for (let j = i + 1; j < boxes.length; j++) {
      if (aabbOverlap(boxes[i], boxes[j])) {
        colliding.add(boxes[i].id);
        colliding.add(boxes[j].id);
      }
    }
  }

  return colliding;
}
