import { memo, useState, useRef, useEffect } from 'react'
import { Position, NodeResizer, useReactFlow, type NodeProps } from '@xyflow/react'
import { BaseNode, BaseNodeHeader, BaseNodeContent } from '../ui/base-node'
import { BaseHandle } from '../ui/base-handle'
import { NodeStatusIndicator, type NodeStatus } from '../ui/node-status-indicator'
import { NodeTooltip, NodeTooltipTrigger, NodeTooltipContent } from '../ui/node-tooltip'
import { getDeviceRenderConfig, CATEGORY_LABELS } from './deviceRegistry'
import { cn } from '@/lib/utils'
import type { DeviceProperties } from '@/types'

export interface DeviceNodeData {
  label: string
  deviceType: string
  category?: string
  properties: DeviceProperties
  [key: string]: unknown
}

function TooltipRow({ label, value }: { label: string; value: string | null | undefined }) {
  if (!value) return null
  return (
    <div className="flex gap-2">
      <span className="text-[10px] uppercase tracking-wider text-muted-foreground">{label}</span>
      <span className="text-xs font-mono text-primary">{value}</span>
    </div>
  )
}

const NODE_DEFAULT = 120  // default square side in px
const NODE_MIN = 80       // minimum square side in px
const NODE_MAX = 280      // maximum square side in px

function DeviceNodeComponent({ id, data, selected, width, height }: NodeProps) {
  const nodeData = data as unknown as DeviceNodeData
  const { icon: Icon, color, accentClass, surfaceClass, category } = getDeviceRenderConfig(nodeData.deviceType, nodeData.category)
  const status = (nodeData.properties?.status || 'unknown') as NodeStatus
  const ip = nodeData.properties?.ip
  const props = nodeData.properties || {}

  // Use the shorter dimension so content never overflows a non-square node
  const size = Math.min(width ?? NODE_DEFAULT, height ?? NODE_DEFAULT)
  const scale = size / NODE_DEFAULT

  // Icon: 28px at default, clamped to [14, 72]
  const iconPx = Math.round(Math.max(14, Math.min(72, scale * 28)))
  // Label font: 11px at default, clamped to [9, 20]
  const labelPx = Math.max(9, Math.min(20, Math.round(scale * 11)))
  // IP font: 9px at default, clamped to [8, 16]
  const ipPx = Math.max(8, Math.min(16, Math.round(scale * 9)))
  const metaPx = Math.max(8, Math.min(11, Math.round(scale * 8)))
  const iconPlateSize = Math.round(Math.max(34, Math.min(82, scale * 50)))

  const [editing, setEditing] = useState(false)
  const [labelValue, setLabelValue] = useState(nodeData.label ?? '')
  const inputRef = useRef<HTMLInputElement>(null)
  const { updateNodeData } = useReactFlow()

  useEffect(() => {
    if (editing) {
      inputRef.current?.focus()
      inputRef.current?.select()
    }
  }, [editing])

  // Sync if data.label changes externally (e.g. undo/redo)
  useEffect(() => {
    if (!editing) setLabelValue(nodeData.label ?? '')
  }, [nodeData.label, editing])

  const hasTooltipContent = props.hostname || props.ip || props.vendor || props.model || props.role || props.notes

  return (
    <>
      <NodeResizer
        isVisible={selected}
        minWidth={NODE_MIN}
        minHeight={NODE_MIN}
        maxWidth={NODE_MAX}
        maxHeight={NODE_MAX}
        keepAspectRatio
        lineStyle={{ borderColor: 'var(--color-accent)', borderWidth: 1 }}
        handleStyle={{ width: 8, height: 8, borderColor: 'var(--color-accent)', background: 'var(--color-card)' }}
      />
      <NodeStatusIndicator status={status}>
        <NodeTooltip>
          <NodeTooltipTrigger>
            <BaseNode className="group h-full w-full bg-card">
              <div className={cn('pointer-events-none absolute inset-x-0 top-0 h-10 bg-gradient-to-b opacity-80', surfaceClass)} />
              <BaseNodeHeader className="flex h-full flex-col items-center justify-center gap-2 px-2 py-3">
                <div
                  className={cn(
                    'relative flex items-center justify-center rounded-xl border transition-colors',
                    accentClass,
                  )}
                  style={{ width: iconPlateSize, height: iconPlateSize }}
                >
                  <div className="absolute inset-[4px] rounded-[10px] border border-white/[0.06] bg-sidebar/50" />
                  <div className="relative z-10">
                    <Icon size={iconPx} style={{ color }} />
                  </div>
                </div>
                {editing ? (
                  <input
                    ref={inputRef}
                    value={labelValue}
                    onChange={e => setLabelValue(e.target.value)}
                    onBlur={() => {
                      setEditing(false)
                      if (labelValue !== nodeData.label) {
                        updateNodeData(id, { ...nodeData, label: labelValue })
                      }
                    }}
                    onKeyDown={e => {
                      if (e.key === 'Enter') inputRef.current?.blur()
                      if (e.key === 'Escape') {
                        setLabelValue(nodeData.label ?? '')
                        setEditing(false)
                      }
                      e.stopPropagation()
                    }}
                    style={{ fontSize: labelPx }}
                    className="bg-transparent border-none outline-none text-center text-primary font-medium w-4/5"
                  />
                ) : (
                  <span
                    style={{ fontSize: labelPx }}
                    className="max-w-[88%] cursor-default text-center font-medium leading-tight text-primary line-clamp-2"
                    onDoubleClick={e => {
                      e.stopPropagation()
                      setEditing(true)
                    }}
                  >
                    {labelValue}
                  </span>
                )}
                <span
                  style={{ fontSize: metaPx }}
                  className="text-[9px] uppercase tracking-[0.16em] text-muted"
                >
                  {CATEGORY_LABELS[category] ?? nodeData.deviceType.replace(/-/g, ' ')}
                </span>
              </BaseNodeHeader>
              {ip && (
                <BaseNodeContent className="items-center pt-0 pb-2">
                  <span
                    className="rounded-full border border-default bg-page/70 px-2 py-0.5 font-mono text-muted-foreground"
                    style={{ fontSize: ipPx }}
                  >
                    {ip}
                  </span>
                </BaseNodeContent>
              )}
              <BaseHandle type="target" position={Position.Top} />
              <BaseHandle type="source" position={Position.Bottom} />
              <BaseHandle type="target" position={Position.Left} id="left" />
              <BaseHandle type="source" position={Position.Right} id="right" />
            </BaseNode>
          </NodeTooltipTrigger>
          {hasTooltipContent && (
            <NodeTooltipContent position={Position.Top}>
              <div className="flex flex-col gap-1 min-w-[140px]">
                <TooltipRow label="Host" value={props.hostname} />
                <TooltipRow label="IP" value={props.ip} />
                {(props.vendor || props.model) && (
                  <TooltipRow label="HW" value={[props.vendor, props.model].filter(Boolean).join(' ')} />
                )}
                <TooltipRow label="Role" value={props.role} />
                {props.notes && (
                  <TooltipRow label="Notes" value={props.notes.length > 100 ? props.notes.slice(0, 100) + '...' : props.notes} />
                )}
              </div>
            </NodeTooltipContent>
          )}
        </NodeTooltip>
      </NodeStatusIndicator>
    </>
  )
}

export const DeviceNode = memo(DeviceNodeComponent)
