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 door placement. */
const MAX_WALL_DISTANCE = 0.5;

/** Default door width in meters. */
export const DEFAULT_DOOR_WIDTH = 0.9;

/** Default door height in meters. */
export const DEFAULT_DOOR_HEIGHT = 2.1;

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

/**
 * Compute a door placement preview from a cursor position.
 * Returns null if no wall is close enough.
 */
export function computeDoorPreview(
  worldPoint: Point,
  walls: readonly Wall[],
  existingOpenings: readonly WallOpening[],
  width: number = DEFAULT_DOOR_WIDTH,
): DoorPlacementPreview | 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 door 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 door.
 */
export function createDoorOpening(
  roomId: string,
  wallId: string,
  positionAlongWall: number,
  width: number = DEFAULT_DOOR_WIDTH,
  height: number = DEFAULT_DOOR_HEIGHT,
): WallOpening {
  return {
    id: generateLocalId(),
    roomId,
    wallId,
    type: 'DOOR',
    positionAlongWall,
    width,
    height,
    elevationFromFloor: 0,
    openDirection: 'LEFT',
    // Openings store canonical (positionAlongWall = center, elevationFromFloor = bottom).
    // The default anchor matches that convention; the user may change it in
    // the properties panel as a view-only display preference.
    positionAnchor: { ...DEFAULT_POSITION_ANCHOR, vertical: 'bottom' },
    // Doors don't use grid subdivision — set to 1×1 so the renderer
    // draws no internal mullions. Default kept for uniformity with the
    // shared WallOpening type.
    gridCols: 1,
    gridRows: 1,
    // Doors ignore slopeDepth (window-only field); kept at 0 for type completeness.
    slopeDepth: 0,
    // Default frame thickness matches the legacy constant in DoorOpening.tsx
    // so newly placed doors look identical to existing ones until edited.
    frameThickness: 0.03,
  };
}
