import type { Point, Wall, WallOpening } from '@house-plan-maker/shared';
import { DEFAULT_POSITION_ANCHOR } from '@house-plan-maker/shared';
import { findNearestWall, wallLength } from '../utils/wallUtils';
import { generateLocalId } from '../utils/geometry';
import { hasOverlap } from '../utils/openingUtils';

/** Maximum distance (in meters) to the nearest wall for window placement. */
const MAX_WALL_DISTANCE = 0.5;

/** Default window width in meters. */
export const DEFAULT_WINDOW_WIDTH = 1.2;

/** Default window height in meters. */
export const DEFAULT_WINDOW_HEIGHT = 1.4;

/** Default window elevation from floor in meters. */
export const DEFAULT_WINDOW_ELEVATION = 0.9;

export interface WindowPlacementPreview {
  readonly wall: Wall;
  readonly positionAlongWall: number;
  readonly snappedPoint: Point;
  readonly width: number;
  readonly isValid: boolean;
}

/**
 * Compute a window placement preview from a cursor position.
 * Returns null if no wall is close enough.
 */
export function computeWindowPreview(
  worldPoint: Point,
  walls: readonly Wall[],
  existingOpenings: readonly WallOpening[],
  width: number = DEFAULT_WINDOW_WIDTH,
): WindowPlacementPreview | null {
  const nearest = findNearestWall(worldPoint, walls);
  if (!nearest || nearest.distance > MAX_WALL_DISTANCE) {
    return null;
  }

  const wLen = wallLength(nearest.wall);
  const halfWidth = width / 2;

  // Clamp position so the window fits within the wall
  const clampedPos = Math.max(halfWidth, Math.min(wLen - halfWidth, nearest.positionAlongWall));

  // Check for overlap with existing openings on the same wall
  const isValid = !hasOverlap(nearest.wall.id, clampedPos, width, existingOpenings);

  return {
    wall: nearest.wall,
    positionAlongWall: clampedPos,
    snappedPoint: nearest.projected,
    width,
    isValid,
  };
}

/**
 * Create a WallOpening object for a window.
 */
export function createWindowOpening(
  roomId: string,
  wallId: string,
  positionAlongWall: number,
  width: number = DEFAULT_WINDOW_WIDTH,
  height: number = DEFAULT_WINDOW_HEIGHT,
  elevation: number = DEFAULT_WINDOW_ELEVATION,
): WallOpening {
  return {
    id: generateLocalId(),
    roomId,
    wallId,
    type: 'WINDOW',
    positionAlongWall,
    width,
    height,
    elevationFromFloor: elevation,
    openDirection: 'LEFT',
    positionAnchor: { ...DEFAULT_POSITION_ANCHOR, vertical: 'bottom' },
    // Default to a classic 2×2 grid (one vertical + one horizontal mullion).
    // The user can change this in the properties panel after placing.
    gridCols: 2,
    gridRows: 2,
    // No reveal slope by default — user can opt in via the properties panel.
    slopeDepth: 0,
    frameThickness: 0.03,
  };
}
