import { memo, useMemo } from 'react';
import { Group, Circle } from 'react-konva';
import type { Point, ElectricalItem } from '@house-plan-maker/shared';
import { anchorOffsetToCenter, DEFAULT_OUTLET_WIDTH, DEFAULT_OUTLET_HEIGHT } from '@house-plan-maker/shared';
import {
  OutletSymbol,
  SingleSwitchSymbol,
  DoubleSwitchSymbol,
  DimmerSwitchSymbol,
  JunctionBoxSymbol,
  CeilingLightSymbol,
  WallLightSymbol,
  CableRouteSymbol,
  getElectricalVariant,
} from '../symbols/electrical';
import { getCableWaypoints } from '../tools/ElectricalTool';
import { getLightCoverageRadius } from '../utils/lightCoverage';

interface ElectricalLayerProps {
  readonly items: readonly ElectricalItem[];
  readonly zoom: number;
  readonly panOffset: Point;
  readonly selectedIds: ReadonlySet<string>;
  readonly visible?: boolean;
  /** Physical width of a single outlet face plate (meters). Used to size outlet boundaries. */
  readonly outletWidth?: number;
  /** Physical height of a single outlet face plate (meters). Used to size outlet boundaries. */
  readonly outletHeight?: number;
}

const ELECTRICAL_COLOR = '#d63384';
const SELECTED_COLOR = '#4c6ef5';
const LIGHT_COVERAGE_COLOR = 'rgba(255, 235, 59, 0.12)';
const LIGHT_COVERAGE_STROKE = 'rgba(255, 235, 59, 0.3)';

function toScreen(point: Point, zoom: number, panOffset: Point): { x: number; y: number } {
  return {
    x: point.x * zoom + panOffset.x,
    y: point.y * zoom + panOffset.y,
  };
}

export const ElectricalLayer = memo(function ElectricalLayer({
  items,
  zoom,
  panOffset,
  selectedIds,
  visible = true,
  outletWidth = DEFAULT_OUTLET_WIDTH,
  outletHeight = DEFAULT_OUTLET_HEIGHT,
}: ElectricalLayerProps) {
  const scale = Math.max(0.6, Math.min(1.5, zoom / 100));
  // Convert real-world outlet dimensions to screen pixels for the current zoom.
  const outletWidthPx = outletWidth * zoom;
  const outletHeightPx = outletHeight * zoom;

  const renderedItems = useMemo(() => {
    if (!visible) return [];
    return items.filter((item) => item.type !== 'CABLE_ROUTE');
  }, [items, visible]);

  const cableItems = useMemo(() => {
    if (!visible) return [];
    return items.filter((item) => item.type === 'CABLE_ROUTE');
  }, [items, visible]);

  return (
    <Group listening={false} visible={visible}>
      {/* Cable routes first (below symbols) */}
      {cableItems.map((item) => {
        const waypoints = getCableWaypoints(item);
        const screenPoints: number[] = [];
        for (const wp of waypoints) {
          const sp = toScreen(wp, zoom, panOffset);
          screenPoints.push(sp.x, sp.y);
        }
        return (
          <CableRouteSymbol
            key={item.id}
            points={screenPoints}
            color={ELECTRICAL_COLOR}
            isSelected={selectedIds.has(item.id)}
          />
        );
      })}

      {/* Electrical symbols */}
      {renderedItems.map((item) => {
        const screen = toScreen({ x: item.x, y: item.y }, zoom, panOffset);
        const isSelected = selectedIds.has(item.id);
        const color = isSelected ? SELECTED_COLOR : ELECTRICAL_COLOR;
        const variant = getElectricalVariant(item.metadata);

        // Bounding box for outlets is count * outletWidth × outletHeight; for
        // other symbols anchor offset is irrelevant (legacy symbols are point-
        // based) but we still respect a non-default anchor by treating the
        // symbol bounding box as a unit cell so the math degenerates to zero
        // when anchor is middle/middle.
        const bboxWidthPx =
          item.type === 'OUTLET' ? Math.max(1, item.count) * outletWidthPx : 0;
        const bboxHeightPx = item.type === 'OUTLET' ? outletHeightPx : 0;
        const offset = anchorOffsetToCenter(item.positionAnchor, bboxWidthPx, bboxHeightPx);

        return (
          <Group key={item.id}>
            {/* Light coverage circle (only for selected light fixtures) */}
            {isSelected && renderLightCoverage(item, zoom, panOffset)}

            {/* Symbol */}
            {renderElectricalSymbol({
              type: item.type,
              variant,
              count: item.count,
              x: screen.x,
              y: screen.y,
              rotation: item.rotation,
              color,
              scale,
              outletWidthPx,
              outletHeightPx,
              centerOffsetX: offset.dx,
              centerOffsetY: offset.dy,
            })}
          </Group>
        );
      })}
    </Group>
  );
});

function renderLightCoverage(
  item: ElectricalItem,
  zoom: number,
  panOffset: Point,
): React.ReactNode {
  const radius = getLightCoverageRadius(item);
  if (radius == null) return null;

  const screen = toScreen({ x: item.x, y: item.y }, zoom, panOffset);
  const radiusPx = radius * zoom;

  return (
    <Circle
      x={screen.x}
      y={screen.y}
      radius={radiusPx}
      fill={LIGHT_COVERAGE_COLOR}
      stroke={LIGHT_COVERAGE_STROKE}
      strokeWidth={1}
      dash={[6, 3]}
      listening={false}
    />
  );
}

interface RenderSymbolArgs {
  readonly type: string;
  readonly variant: string;
  readonly count: number;
  readonly x: number;
  readonly y: number;
  readonly rotation: number;
  readonly color: string;
  readonly scale: number;
  readonly outletWidthPx: number;
  readonly outletHeightPx: number;
  readonly centerOffsetX: number;
  readonly centerOffsetY: number;
}

function renderElectricalSymbol(args: RenderSymbolArgs): React.ReactNode {
  const { type, variant, count, x, y, rotation, color, scale } = args;
  switch (type) {
    case 'OUTLET':
      return (
        <OutletSymbol
          x={x}
          y={y}
          rotation={rotation}
          color={color}
          count={count}
          outletWidthPx={args.outletWidthPx}
          outletHeightPx={args.outletHeightPx}
          centerOffsetX={args.centerOffsetX}
          centerOffsetY={args.centerOffsetY}
        />
      );
    case 'SWITCH':
      switch (variant) {
        case 'double':
          return <DoubleSwitchSymbol x={x} y={y} rotation={rotation} color={color} scale={scale} />;
        case 'dimmer':
          return <DimmerSwitchSymbol x={x} y={y} rotation={rotation} color={color} scale={scale} />;
        default:
          return <SingleSwitchSymbol x={x} y={y} rotation={rotation} color={color} scale={scale} />;
      }
    case 'JUNCTION_BOX':
      return <JunctionBoxSymbol x={x} y={y} rotation={rotation} color={color} scale={scale} />;
    case 'LIGHT_CEILING':
      return <CeilingLightSymbol x={x} y={y} rotation={rotation} color={color} scale={scale} />;
    case 'LIGHT_WALL':
      return <WallLightSymbol x={x} y={y} rotation={rotation} color={color} scale={scale} />;
    default:
      return null;
  }
}
