import type { Point, Wall, ElectricalItem, ElectricalType } from '@house-plan-maker/shared';
import { DEFAULT_POSITION_ANCHOR } from '@house-plan-maker/shared';
import { findNearestWall, wallAngle } from '../utils/wallUtils';
import { generateLocalId } from '../utils/geometry';
import { DEFAULT_ELEVATIONS } from '../utils/projectionMapping';
import { normalizeAngleDegrees } from '../utils/angle';
import type { ElectricalSymbolDef } from '../symbols/electrical';

/** Maximum snap distance to wall (meters). */
const WALL_SNAP_DISTANCE = 0.5;

export interface ElectricalPlacementPreview {
  readonly x: number;
  readonly y: number;
  readonly rotation: number;
  readonly wallId: string | null;
  readonly isValid: boolean;
}

/**
 * Compute electrical item placement preview.
 * Wall-mounted items snap to the nearest wall; ceiling items place freely.
 */
export function computeElectricalPreview(
  worldPoint: Point,
  walls: readonly Wall[],
  symbolDef: ElectricalSymbolDef,
): ElectricalPlacementPreview {
  if (symbolDef.wallMounted) {
    const nearest = findNearestWall(worldPoint, walls);
    if (nearest && nearest.distance <= WALL_SNAP_DISTANCE) {
      const angle = wallAngle(nearest.wall);
      return {
        x: nearest.projected.x,
        y: nearest.projected.y,
        rotation: normalizeAngleDegrees((angle * 180) / Math.PI),
        wallId: nearest.wall.id,
        isValid: true,
      };
    }
    // Too far from any wall
    return {
      x: worldPoint.x,
      y: worldPoint.y,
      rotation: 0,
      wallId: null,
      isValid: false,
    };
  }

  // Ceiling/free placement
  return {
    x: worldPoint.x,
    y: worldPoint.y,
    rotation: 0,
    wallId: null,
    isValid: true,
  };
}

/**
 * Resolve default elevation for an electrical item type.
 * Wall-mounted types get their standard elevation, ceiling lights get wall height,
 * and cable routes remain null.
 */
export function getDefaultElevation(
  type: ElectricalType,
  wallHeight?: number,
): number | null {
  if (type === 'LIGHT_CEILING') {
    return wallHeight ?? 2.5;
  }
  if (type === 'CABLE_ROUTE') {
    return null;
  }
  return DEFAULT_ELEVATIONS[type] ?? null;
}

/**
 * Create an ElectricalItem from placement data.
 */
export function createElectricalItemFromPlacement(
  roomId: string,
  preview: ElectricalPlacementPreview,
  type: ElectricalType,
  variant?: string,
  wallHeight?: number,
): ElectricalItem {
  // Outlets no longer use a `variant` — count is the source of truth. For all
  // other types we still pass variant through metadata (e.g., switches).
  const metadata: Record<string, unknown> | null =
    type !== 'OUTLET' && variant ? { variant } : null;

  return {
    id: generateLocalId(),
    roomId,
    type,
    x: preview.x,
    y: preview.y,
    wallId: preview.wallId,
    elevationFromFloor: getDefaultElevation(type, wallHeight),
    rotation: preview.rotation,
    count: 1,
    positionAnchor: DEFAULT_POSITION_ANCHOR,
    label: null,
    metadata,
  };
}

/**
 * Compute total cable route length from a list of electrical items of type CABLE_ROUTE.
 * Each cable route stores waypoints in metadata.points as Point[].
 * Returns length in meters.
 */
export function computeCableRouteLength(electricalItems: readonly ElectricalItem[]): number {
  let total = 0;

  for (const item of electricalItems) {
    if (item.type !== 'CABLE_ROUTE') continue;
    const points = getCableWaypoints(item);
    if (points.length < 2) continue;

    for (let i = 1; i < points.length; i++) {
      const dx = points[i].x - points[i - 1].x;
      const dy = points[i].y - points[i - 1].y;
      total += Math.sqrt(dx * dx + dy * dy);
    }
  }

  return total;
}

/** Extract cable waypoints from metadata. */
export function getCableWaypoints(item: ElectricalItem): readonly Point[] {
  if (!item.metadata || !Array.isArray(item.metadata['points'])) {
    return [{ x: item.x, y: item.y }];
  }
  return item.metadata['points'] as Point[];
}
