import { memo, useMemo } from 'react'
import type { Plant } from '@/lib/plants'
import type { EditorPlanting } from '@/lib/plantings'
import { PlopMarker, SEMANTIC_FAR } from './PlopMarker'
import { DIMMED_OPACITY, objectTransform } from './shared'
import type { EditorObject } from './types'

/** The most common plant color among an object's plops (for the far-zoom tint). */
function dominantColor(plops: EditorPlanting[], plantsById: Map<number, Plant>): string | null {
  const freq = new Map<string, number>()
  for (const p of plops) {
    const c = plantsById.get(p.plantId)?.color
    if (c) freq.set(c, (freq.get(c) ?? 0) + 1)
  }
  let best: string | null = null
  let bestN = 0
  for (const [c, n] of freq) {
    if (n > bestN) {
      best = c
      bestN = n
    }
  }
  return best
}

/**
 * Renders every active plop, grouped under its parent object's translate+rotate
 * transform so plops track the bed when it's moved/rotated. Far zoom adds a
 * dominant-plant tint over each planted object so beds read at a glance. Focus
 * mode dims plops on non-focused objects.
 */
export const PlopLayer = memo(function PlopLayer({
  objects,
  plantings,
  plantsById,
  scale,
  focusedObjectId,
  selectedPlantingId,
  onSelectPlop,
}: {
  objects: EditorObject[]
  plantings: EditorPlanting[]
  plantsById: Map<number, Plant>
  scale: number
  focusedObjectId: number | null
  selectedPlantingId: number | null
  onSelectPlop: (id: number) => void
}) {
  // Group plops by object once per plops change (not on every pan/zoom frame).
  const byObject = useMemo(() => {
    const m = new Map<number, EditorPlanting[]>()
    for (const p of plantings) {
      const arr = m.get(p.objectId)
      if (arr) arr.push(p)
      else m.set(p.objectId, [p])
    }
    return m
  }, [plantings])
  const far = scale < SEMANTIC_FAR

  return (
    <>
      {objects.map((o) => {
        const plops = byObject.get(o.id)
        if (!plops || plops.length === 0) return null
        const dimmed = focusedObjectId != null && focusedObjectId !== o.id
        const halfW = o.widthCm / 2
        const halfH = o.heightCm / 2
        const tint = far ? dominantColor(plops, plantsById) : null
        return (
          <g key={o.id} transform={objectTransform(o)} opacity={dimmed ? DIMMED_OPACITY : 1}>
            {tint &&
              (o.shape === 'circle' ? (
                <ellipse cx={0} cy={0} rx={halfW} ry={halfH} fill={tint} fillOpacity={0.5} pointerEvents="none" />
              ) : (
                <rect x={-halfW} y={-halfH} width={halfW * 2} height={halfH * 2} fill={tint} fillOpacity={0.5} pointerEvents="none" />
              ))}
            {plops.map((p) => (
              <PlopMarker
                key={p.id}
                plop={p}
                plant={plantsById.get(p.plantId)}
                scale={scale}
                selected={p.id === selectedPlantingId}
                onSelect={onSelectPlop}
              />
            ))}
          </g>
        )
      })}
    </>
  )
})
