import {
  ShapeUtil,
  TLHandle,
  TLShapePartial,
  Rectangle2d,
  HTMLContainer,
  IndexKey,
} from 'tldraw'
import { FoerdererShape, foerdererShapeProps } from './shape-types'
import { FOERDERER_CONFIG as CFG } from './shape-config'

/** Förderer: Doppellinie (durchgezogen + gestrichelt) mit Endpunkt-Kreisen. */
export class FoerdererShapeUtil extends ShapeUtil<FoerdererShape> {
  static override type = 'foerderer' as const
  static override props = foerdererShapeProps

  getDefaultProps(): FoerdererShape['props'] {
    return {
      endX: CFG.defaultEndX,
      endY: CFG.defaultEndY,
      spacing: CFG.defaultSpacing,
      label: 'Förderer',
    }
  }

  getGeometry(shape: FoerdererShape) {
    const { endX, endY, spacing } = shape.props
    // Senkrechte zum Richtungsvektor für Spacing-Offset
    const len = Math.sqrt(endX * endX + endY * endY) || 1
    const perpX = (-endY / len) * spacing
    const perpY = (endX / len) * spacing

    // Alle 4 Eckpunkte der beiden Linien + Endpunkt-Kreise
    const xs = [0, endX, perpX, endX + perpX]
    const ys = [0, endY, perpY, endY + perpY]
    const pad = CFG.endpointRadius
    const minX = Math.min(...xs) - pad
    const minY = Math.min(...ys) - pad
    const maxX = Math.max(...xs) + pad
    const maxY = Math.max(...ys) + pad

    return new Rectangle2d({
      width: maxX - minX,
      height: maxY - minY,
      isFilled: false,
    })
  }

  override canResize() {
    return false
  }

  override onRotate(initial: FoerdererShape, current: FoerdererShape): TLShapePartial<FoerdererShape> {
    const HALF_PI = Math.PI / 2
    const snapped = Math.round(current.rotation / HALF_PI) * HALF_PI
    return { id: current.id, type: 'foerderer', x: initial.x, y: initial.y, rotation: snapped }
  }

  /** Offset vom Shape-Ursprung zum Geometry-Ursprung (wegen negativer Koordinaten) */
  private _getOffset(shape: FoerdererShape) {
    const { endX, endY, spacing } = shape.props
    const len = Math.sqrt(endX * endX + endY * endY) || 1
    const perpX = (-endY / len) * spacing
    const perpY = (endX / len) * spacing
    const xs = [0, endX, perpX, endX + perpX]
    const ys = [0, endY, perpY, endY + perpY]
    const pad = CFG.endpointRadius
    return {
      ox: Math.min(...xs) - pad,
      oy: Math.min(...ys) - pad,
    }
  }

  override getHandles(shape: FoerdererShape): TLHandle[] {
    const { ox, oy } = this._getOffset(shape)
    return [
      {
        id: 'start',
        type: 'vertex',
        x: 0 - ox,
        y: 0 - oy,
        index: 'a1' as IndexKey,
        canSnap: true,
      },
      {
        id: 'end',
        type: 'vertex',
        x: shape.props.endX - ox,
        y: shape.props.endY - oy,
        index: 'a2' as IndexKey,
        canSnap: true,
      },
    ]
  }

  override onHandleDrag(
    shape: FoerdererShape,
    { handle }: { handle: TLHandle }
  ): TLShapePartial<FoerdererShape> | void {
    if (handle.id === 'end') {
      const { ox, oy } = this._getOffset(shape)
      const newEndX = handle.x + ox
      const newEndY = handle.y + oy
      const len = Math.sqrt(newEndX * newEndX + newEndY * newEndY)
      if (len < CFG.minLength) return

      return {
        id: shape.id,
        type: 'foerderer',
        props: { ...shape.props, endX: newEndX, endY: newEndY },
      }
    }

    if (handle.id === 'start') {
      // Start-Handle: Shape-Position verschieben, End bleibt in Weltkoordinaten
      const pagePoint = this.editor.inputs.currentPagePoint
      const dx = pagePoint.x - shape.x
      const dy = pagePoint.y - shape.y
      const newEndX = shape.props.endX - dx
      const newEndY = shape.props.endY - dy
      const len = Math.sqrt(newEndX * newEndX + newEndY * newEndY)
      if (len < CFG.minLength) return

      return {
        id: shape.id,
        type: 'foerderer',
        x: pagePoint.x,
        y: pagePoint.y,
        props: { ...shape.props, endX: newEndX, endY: newEndY },
      }
    }
  }

  component(shape: FoerdererShape) {
    const { endX, endY, spacing } = shape.props
    const { ox, oy } = this._getOffset(shape)

    // Senkrechte für parallele Linie
    const len = Math.sqrt(endX * endX + endY * endY) || 1
    const perpX = (-endY / len) * spacing
    const perpY = (endX / len) * spacing

    // Punkte relativ zum SVG-Ursprung (offset-korrigiert)
    const sx = 0 - ox
    const sy = 0 - oy
    const ex = endX - ox
    const ey = endY - oy

    const bounds = this.getGeometry(shape).getBounds()
    const totalW = bounds.w
    const totalH = bounds.h

    return (
      <HTMLContainer>
        <svg
          width={totalW}
          height={totalH}
          style={{ overflow: 'visible' }}
        >
          {/* Durchgezogene Linie */}
          <line
            x1={sx} y1={sy} x2={ex} y2={ey}
            stroke="black" strokeWidth={CFG.strokeWidth}
          />
          {/* Gestrichelte parallele Linie */}
          <line
            x1={sx + perpX} y1={sy + perpY}
            x2={ex + perpX} y2={ey + perpY}
            stroke="black" strokeWidth={CFG.strokeWidth}
            strokeDasharray="8 4"
          />
          {/* Start-Kreis */}
          <circle
            cx={sx} cy={sy} r={CFG.endpointRadius}
            fill="black" stroke="black" strokeWidth={1}
          />
          {/* End-Kreis */}
          <circle
            cx={ex} cy={ey} r={CFG.endpointRadius}
            fill="black" stroke="black" strokeWidth={1}
          />
          {/* Label */}
          <text
            x={(sx + ex) / 2}
            y={(sy + ey) / 2 - 12}
            textAnchor="middle"
            dominantBaseline="central"
            fontSize={14}
            fill="#666"
            style={{ pointerEvents: 'none', userSelect: 'none' }}
          >
            {shape.props.label}
          </text>
        </svg>
      </HTMLContainer>
    )
  }

  indicator(shape: FoerdererShape) {
    const bounds = this.getGeometry(shape).getBounds()
    return (
      <rect x={0} y={0} width={bounds.w} height={bounds.h} />
    )
  }
}
