import type { Point, Wall, WallOpening, ElectricalItem, FurnitureItem, RoomFull, Annotation } from '@house-plan-maker/shared';

// ── Tool Types ──

export type EditorToolType = 'select' | 'door' | 'window' | 'electrical' | 'furniture' | 'measure' | 'annotate';

export interface CanvasPointerEvent {
  /** Position in world/meter coordinates. */
  readonly worldPoint: Point;
  /** Position in screen/pixel coordinates. */
  readonly screenPoint: Point;
  /** Whether shift key is held. */
  readonly shiftKey: boolean;
  /** Whether ctrl/cmd key is held. */
  readonly ctrlKey: boolean;
  /** The original Konva event (if available). */
  readonly originalEvent?: MouseEvent;
}

// ── Selection ──

export type SelectableElementType = 'wall' | 'opening' | 'electrical' | 'furniture';

export interface SelectableElement {
  readonly id: string;
  readonly type: SelectableElementType;
}

// ── Editor State ──

/** Layer visibility toggles. */
export interface LayerVisibility {
  readonly walls: boolean;
  readonly electrical: boolean;
  readonly furniture: boolean;
  readonly measurements: boolean;
  readonly annotations: boolean;
  /**
   * Whether the stretch-ceiling visualization (tinted plane + outline in 3D,
   * tinted band + dashed line in projection) is rendered. The underlying
   * `stretchCeilingOffset` value on the room is untouched when toggled —
   * this flag is a view-only layer switch.
   */
  readonly stretchCeiling: boolean;
}

export interface EditorState {
  readonly room: RoomFull;
  readonly walls: readonly Wall[];
  readonly openings: readonly WallOpening[];
  readonly electricalItems: readonly ElectricalItem[];
  readonly furnitureItems: readonly FurnitureItem[];
  readonly selectedIds: ReadonlySet<string>;
  readonly activeTool: EditorToolType;
  readonly zoom: number;
  readonly panOffset: Point;
  readonly gridSize: number;
  readonly gridVisible: boolean;
  readonly snapEnabled: boolean;
  readonly snapGranularity: number;
  readonly layerVisibility: LayerVisibility;
  /** Index into ELECTRICAL_SYMBOL_DEFS for electrical tool. */
  readonly selectedElectricalIndex: number | null;
  /** Index into FURNITURE_DEFS for furniture tool. */
  readonly selectedFurnitureIndex: number | null;
  readonly annotations: readonly Annotation[];
  /** Furniture IDs whose dimension/offset projection should be drawn on every wall view. */
  readonly furnitureProjectionIds: ReadonlySet<string>;
  /** Global multiplier applied to every furniture item's render opacity. */
  readonly globalFurnitureOpacity: number;
}

// ── Undo/Redo Commands ──

export interface EditorCommand {
  readonly description: string;
  execute(): void;
  undo(): void;
}

// ── Editor Actions ──

export type EditorAction =
  | { readonly type: 'SET_ROOM'; readonly room: RoomFull }
  | { readonly type: 'UPDATE_ROOM_PROPS'; readonly props: Partial<Pick<RoomFull, 'floorType' | 'wallColor' | 'wallFinish' | 'wallHeight' | 'plinthHeight' | 'plinthThickness' | 'stretchCeilingOffset' | 'outletWidth' | 'outletHeight'>> }
  | { readonly type: 'SET_WALLS'; readonly walls: readonly Wall[] }
  | { readonly type: 'UPDATE_WALL'; readonly wall: Wall }
  | { readonly type: 'ADD_OPENING'; readonly opening: WallOpening }
  | { readonly type: 'UPDATE_OPENING'; readonly opening: WallOpening }
  | { readonly type: 'REMOVE_OPENING'; readonly id: string }
  | { readonly type: 'ADD_ELECTRICAL'; readonly item: ElectricalItem }
  | { readonly type: 'UPDATE_ELECTRICAL'; readonly item: ElectricalItem }
  | { readonly type: 'REMOVE_ELECTRICAL'; readonly id: string }
  | { readonly type: 'ADD_FURNITURE'; readonly item: FurnitureItem }
  | { readonly type: 'UPDATE_FURNITURE'; readonly item: FurnitureItem }
  | { readonly type: 'REMOVE_FURNITURE'; readonly id: string }
  | { readonly type: 'SET_SELECTED'; readonly ids: ReadonlySet<string> }
  | { readonly type: 'ADD_TO_SELECTION'; readonly id: string }
  | { readonly type: 'REMOVE_FROM_SELECTION'; readonly id: string }
  | { readonly type: 'CLEAR_SELECTION' }
  | { readonly type: 'SET_TOOL'; readonly tool: EditorToolType }
  | { readonly type: 'SET_ZOOM'; readonly zoom: number }
  | { readonly type: 'SET_PAN_OFFSET'; readonly offset: Point }
  // Atomic zoom + pan update. Used by auto-fit so we don't flicker through
  // an intermediate (newZoom, oldPan) state between two separate dispatches.
  | { readonly type: 'SET_VIEW'; readonly zoom: number; readonly offset: Point }
  | { readonly type: 'SET_GRID_SIZE'; readonly gridSize: number }
  | { readonly type: 'TOGGLE_GRID' }
  | { readonly type: 'TOGGLE_SNAP' }
  | { readonly type: 'SET_SNAP_GRANULARITY'; readonly granularity: number }
  | { readonly type: 'TOGGLE_LAYER'; readonly layer: keyof LayerVisibility }
  | { readonly type: 'SET_ELECTRICAL_INDEX'; readonly index: number | null }
  | { readonly type: 'SET_FURNITURE_INDEX'; readonly index: number | null }
  | { readonly type: 'DELETE_SELECTED' }
  | { readonly type: 'SELECT_ALL' }
  // Clipboard
  | { readonly type: 'COPY_SELECTED' }
  | { readonly type: 'PASTE_CLIPBOARD'; readonly items: PastePayload }
  // Alignment
  | { readonly type: 'ALIGN_SELECTED'; readonly alignment: AlignmentDirection }
  // Annotations
  | { readonly type: 'ADD_ANNOTATION'; readonly annotation: Annotation }
  | { readonly type: 'UPDATE_ANNOTATION'; readonly annotation: Annotation }
  | { readonly type: 'REMOVE_ANNOTATION'; readonly id: string }
  // Furniture projection toggle (per-item dimension/offset overlay on wall views)
  | { readonly type: 'TOGGLE_FURNITURE_PROJECTION'; readonly id: string }
  // Global furniture opacity (client-side display setting, multiplied with item.opacity)
  | { readonly type: 'SET_GLOBAL_FURNITURE_OPACITY'; readonly opacity: number }
  // Import
  | {
      readonly type: 'IMPORT_ROOM';
      readonly room: {
        readonly name: string;
        readonly shape: readonly Point[];
        readonly wallHeight: number;
        readonly plinthHeight: number;
        readonly plinthThickness: number;
      };
      readonly walls: readonly Wall[];
      readonly openings: readonly WallOpening[];
      readonly electricalItems: readonly ElectricalItem[];
      readonly furnitureItems: readonly FurnitureItem[];
    }
  // Sync after save (update server IDs without full reload)
  | {
      readonly type: 'SYNC_SAVE';
      readonly walls: readonly Wall[];
      readonly openings: readonly WallOpening[];
      readonly electricalItems: readonly ElectricalItem[];
      readonly furnitureItems: readonly FurnitureItem[];
      readonly annotations?: readonly Annotation[];
      /** Map from old (pre-save) item IDs to new (server) item IDs. */
      readonly idMap?: ReadonlyMap<string, string>;
    };

// ── Alignment ──

export type AlignmentDirection =
  | 'left'
  | 'right'
  | 'top'
  | 'bottom'
  | 'center-h'
  | 'center-v'
  | 'distribute-h'
  | 'distribute-v';

// ── Clipboard ──

export interface PastePayload {
  readonly openings: readonly WallOpening[];
  readonly electricalItems: readonly ElectricalItem[];
  readonly furnitureItems: readonly FurnitureItem[];
  readonly annotations: readonly Annotation[];
  readonly newSelectedIds: ReadonlySet<string>;
}

// ── Zoom/Pan Config ──

export const MIN_ZOOM = 10; // 10 pixels per meter (very zoomed out)
export const MAX_ZOOM = 500; // 500 pixels per meter (very zoomed in)
export const DEFAULT_ZOOM = 100; // 100 pixels per meter
export const ZOOM_SENSITIVITY = 0.001;
export const DEFAULT_GRID_SIZE = 0.1; // 0.1 meters = 10cm

// ── Measurement State ──

export interface MeasurementState {
  readonly startPoint: Point;
  readonly endPoint: Point;
  readonly distance: number;
}

export interface MeasurementResult {
  readonly startPoint: Point;
  readonly endPoint: Point;
  readonly distance: number;
}

// ── Drag State (for selection tool) ──

export interface DragState {
  readonly isDragging: boolean;
  readonly startWorld: Point;
  readonly currentWorld: Point;
  readonly dragType: 'move' | 'select-rect';
}
