import { Button } from './Button'
import type { InboxItemAction } from './InboxItem'
import { KvPanel } from './KvPanel'
import { MapNode, type MapNodeModel } from './MapNode'

export interface MapEdge {
  from: string
  to: string
  dashed?: boolean
  color?: string
}

export interface MapCanvasProps {
  nodes: MapNodeModel[]
  edges: MapEdge[]
  selectedNodeId?: string
  onSelectNode: (id: string) => void
}

function nodeCenter(node: MapNodeModel): { x: number; y: number } {
  return { x: node.x + 8, y: node.y + 6 }
}

function edgePoints(
  from: MapNodeModel,
  to: MapNodeModel,
  width: number,
  height: number,
): { x1: number; y1: number; x2: number; y2: number } {
  const a = nodeCenter(from)
  const b = nodeCenter(to)
  return {
    x1: (a.x / 100) * width,
    y1: (a.y / 100) * height,
    x2: (b.x / 100) * width,
    y2: (b.y / 100) * height,
  }
}

/** `.at` — spatial infrastructure map with SVG edges, positioned nodes, and inspector. */
export function MapCanvas({ nodes, edges, selectedNodeId, onSelectNode }: MapCanvasProps) {
  const selected = nodes.find((node) => node.id === selectedNodeId) ?? nodes[0]
  const nodeById = Object.fromEntries(nodes.map((node) => [node.id, node])) as Record<string, MapNodeModel>

  return (
    <div
      data-testid="map-canvas"
      className="relative min-h-[470px] overflow-hidden rounded-xl border border-border bg-[radial-gradient(ellipse_at_40%_35%,#131a2e_0%,#0a0d18_70%)] text-[12px] text-[#c7d3f0]"
    >
      <svg className="pointer-events-none absolute inset-0 h-full w-full" aria-hidden>
        {edges.map((edge) => {
          const from = nodeById[edge.from]
          const to = nodeById[edge.to]
          if (!from || !to) return null
          const { x1, y1, x2, y2 } = edgePoints(from, to, 1000, 470)
          return (
            <line
              key={`${edge.from}-${edge.to}`}
              x1={x1}
              y1={y1}
              x2={x2}
              y2={y2}
              stroke={edge.color ?? 'rgba(122,162,255,0.35)'}
              strokeWidth={1.5}
              strokeDasharray={edge.dashed ? '5 4' : undefined}
              vectorEffect="non-scaling-stroke"
            />
          )
        })}
      </svg>

      {nodes.map((node) => (
        <MapNode
          key={node.id}
          node={node}
          selected={node.id === selected?.id}
          onSelect={onSelectNode}
        />
      ))}

      {selected ? (
        <aside
          data-testid="map-inspector"
          className="absolute bottom-4 right-4 top-4 flex w-[250px] flex-col rounded-[14px] border border-accent/25 bg-[rgba(13,18,34,0.88)] p-4 backdrop-blur-[10px]"
        >
          <h5 className="text-[13px] text-white">{selected.title}</h5>
          {selected.subtitle ? <div className="mb-3.5 text-[11px] text-[#66759c]">{selected.subtitle}</div> : null}
          <KvPanel rows={selected.inspectorKvs} />
          <div className="mt-auto flex flex-col gap-2">
            {selected.actions.map((action: InboxItemAction) => (
              <Button
                key={action.label}
                variant={action.primary ? 'solid' : 'outline'}
                tone="accent"
                size="sm"
                onClick={action.onClick}
                className="w-full text-[12px]"
              >
                {action.label}
              </Button>
            ))}
          </div>
        </aside>
      ) : null}
    </div>
  )
}