import { useCallback, useState, useEffect } from 'react'
import {
  Trash2, Minus, Spline, GitBranch, CornerUpRight, BringToFront, SendToBack,
  AlignStartVertical, AlignCenterHorizontal, AlignEndVertical,
  AlignStartHorizontal, AlignCenterVertical, AlignEndHorizontal,
  AlignHorizontalSpaceAround, AlignVerticalSpaceAround,
  BoxSelect, Ungroup, MousePointer,
} from 'lucide-react'
import { cn } from '@/lib/utils'
import type { DeviceProperties, DiagramEdge } from '@/types'
import type { Node, Edge } from '@xyflow/react'
import type { DeviceNodeData } from '../nodes/DeviceNode'

interface PropertiesPanelProps {
  selectedNode: Node | null
  selectedEdge: Edge | null
  onNodeUpdate: (nodeId: string, data: Partial<DeviceNodeData>) => void
  onEdgeUpdate: (edgeId: string, data: Partial<DiagramEdge>) => void
  onEdgeTypeChange: (edgeId: string, edgeType: string) => void
  onBringToFront: (nodeId: string) => void
  onSendToBack: (nodeId: string) => void
  onDeleteNode: (nodeId: string) => void
  onDeleteEdge: (edgeId: string) => void
  selectedNodeCount: number
  onAlignLeft: () => void
  onAlignRight: () => void
  onAlignCenterH: () => void
  onAlignTop: () => void
  onAlignBottom: () => void
  onAlignCenterV: () => void
  onDistributeH: () => void
  onDistributeV: () => void
  canAlign: boolean
  canDistribute: boolean
  canGroup: boolean
  canUngroup: boolean
  onGroupSelection: (groupType: string) => void
  onUngroupSelection: () => void
}

type NodeStatus = 'online' | 'offline' | 'degraded' | 'unknown'

const STATUS_CONFIG: Record<NodeStatus, { color: string; label: string }> = {
  online:   { color: '#34d399', label: 'Online' },
  offline:  { color: '#f87171', label: 'Offline' },
  degraded: { color: '#fbbf24', label: 'Degraded' },
  unknown:  { color: '#94a3b8', label: 'Unknown' },
}

const STATUS_OPTIONS = Object.keys(STATUS_CONFIG) as NodeStatus[]
const CONNECTION_TYPE_OPTIONS = ['ethernet', 'fiber', 'wifi', 'vpn', 'vlan', 'wan'] as const

function FieldLabel({ children }: { children: React.ReactNode }) {
  return (
    <label className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
      {children}
    </label>
  )
}

function FieldInput({ value, onChange, placeholder, mono }: {
  value: string
  onChange: (val: string) => void
  placeholder?: string
  mono?: boolean
}) {
  return (
    <input
      type="text"
      value={value}
      onChange={e => onChange(e.target.value)}
      placeholder={placeholder}
      className={cn(
        'w-full rounded border border-default bg-input px-2 py-1.5 text-xs text-primary placeholder:text-muted-foreground focus:border-accent focus:outline-none',
        mono && 'font-mono',
      )}
    />
  )
}

function SectionDivider({ label }: { label: string }) {
  return (
    <div className="flex items-center gap-2 pt-1">
      <span className="whitespace-nowrap text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
        {label}
      </span>
      <div className="flex-1 border-t border-default" />
    </div>
  )
}

const GROUP_TYPES = [
  { value: 'subnet', label: 'Subnet' },
  { value: 'vlan',   label: 'VLAN' },
  { value: 'site',   label: 'Site' },
  { value: 'dmz',    label: 'DMZ' },
  { value: 'custom', label: 'Custom' },
]

export function PropertiesPanel({
  selectedNode,
  selectedEdge,
  onNodeUpdate,
  onEdgeUpdate,
  onEdgeTypeChange,
  onBringToFront,
  onSendToBack,
  onDeleteNode,
  onDeleteEdge,
  selectedNodeCount,
  onAlignLeft,
  onAlignRight,
  onAlignCenterH,
  onAlignTop,
  onAlignBottom,
  onAlignCenterV,
  onDistributeH,
  onDistributeV,
  canAlign,
  canDistribute,
  canGroup,
  canUngroup,
  onGroupSelection,
  onUngroupSelection,
}: PropertiesPanelProps) {
  const [deleteConfirm, setDeleteConfirm] = useState(false)
  const [pendingGroupType, setPendingGroupType] = useState('subnet')

  // Reset confirm state whenever the selection changes
  // eslint-disable-next-line react-hooks/set-state-in-effect
  useEffect(() => { setDeleteConfirm(false) }, [selectedNode?.id, selectedEdge?.id])

  const handlePropertyChange = useCallback((field: keyof DeviceProperties, value: string) => {
    if (!selectedNode) return
    const nodeData = selectedNode.data as unknown as DeviceNodeData
    onNodeUpdate(selectedNode.id, {
      properties: { ...nodeData.properties, [field]: value },
    } as Partial<DeviceNodeData>)
  }, [selectedNode, onNodeUpdate])

  const handleLabelChange = useCallback((value: string) => {
    if (!selectedNode) return
    onNodeUpdate(selectedNode.id, { label: value } as Partial<DeviceNodeData>)
  }, [selectedNode, onNodeUpdate])

  if (!selectedNode && !selectedEdge && selectedNodeCount >= 2) {
    return (
      <div className="w-[260px] border-l border-default bg-sidebar flex flex-col">
        <div className="px-4 py-3 border-b border-default">
          <div className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
            {selectedNodeCount} nodes selected
          </div>
        </div>
        <div className="p-3 flex flex-col gap-4">
          {canAlign && (
            <div>
              <div className="text-[10px] font-medium text-muted uppercase tracking-wider mb-2">Align</div>
              <div className="grid grid-cols-3 gap-1">
                {([
                  { label: 'Left', icon: AlignStartVertical, action: onAlignLeft },
                  { label: 'Center', icon: AlignCenterHorizontal, action: onAlignCenterH },
                  { label: 'Right', icon: AlignEndVertical, action: onAlignRight },
                  { label: 'Top', icon: AlignStartHorizontal, action: onAlignTop },
                  { label: 'Middle', icon: AlignCenterVertical, action: onAlignCenterV },
                  { label: 'Bottom', icon: AlignEndHorizontal, action: onAlignBottom },
                ] as const).map(({ label, icon: Icon, action }) => (
                  <button
                    key={label}
                    onClick={action}
                    title={`Align ${label}`}
                    className="flex flex-col items-center gap-1 p-2 rounded bg-elevated hover:bg-card border border-default hover:border-hover transition-colors text-muted-foreground hover:text-primary"
                  >
                    <Icon size={14} />
                    <span className="text-[9px]">{label}</span>
                  </button>
                ))}
              </div>
            </div>
          )}
          {canDistribute && (
            <div>
              <div className="text-[10px] font-medium text-muted uppercase tracking-wider mb-2">Distribute</div>
              <div className="grid grid-cols-2 gap-1">
                <button
                  onClick={onDistributeH}
                  className="flex items-center gap-1.5 px-2 py-1.5 rounded bg-elevated hover:bg-card border border-default hover:border-hover transition-colors text-muted-foreground hover:text-primary text-xs"
                >
                  <AlignHorizontalSpaceAround size={13} /> Horizontal
                </button>
                <button
                  onClick={onDistributeV}
                  className="flex items-center gap-1.5 px-2 py-1.5 rounded bg-elevated hover:bg-card border border-default hover:border-hover transition-colors text-muted-foreground hover:text-primary text-xs"
                >
                  <AlignVerticalSpaceAround size={13} /> Vertical
                </button>
              </div>
            </div>
          )}
          {(canGroup || canUngroup) && (
            <div className="flex flex-col gap-2">
              <div className="text-[10px] font-medium text-muted uppercase tracking-wider">Grouping</div>
              {canGroup && (
                <div className="flex flex-col gap-1.5">
                  <select
                    value={pendingGroupType}
                    onChange={e => setPendingGroupType(e.target.value)}
                    className="w-full rounded border border-default bg-input px-2 py-1.5 text-xs text-primary focus:border-accent focus:outline-none"
                  >
                    {GROUP_TYPES.map(gt => (
                      <option key={gt.value} value={gt.value}>{gt.label}</option>
                    ))}
                  </select>
                  <button
                    onClick={() => onGroupSelection(pendingGroupType)}
                    className="flex items-center justify-center gap-1.5 px-2 py-1.5 rounded bg-elevated hover:bg-card border border-default hover:border-hover transition-colors text-muted-foreground hover:text-primary text-xs"
                  >
                    <BoxSelect size={13} /> Group into {GROUP_TYPES.find(g => g.value === pendingGroupType)?.label}
                  </button>
                </div>
              )}
              {canUngroup && (
                <button
                  onClick={onUngroupSelection}
                  className="flex items-center justify-center gap-1.5 px-2 py-1.5 rounded bg-elevated hover:bg-card border border-default hover:border-hover transition-colors text-muted-foreground hover:text-primary text-xs"
                >
                  <Ungroup size={13} /> Ungroup
                </button>
              )}
            </div>
          )}
        </div>
      </div>
    )
  }

  if (!selectedNode && !selectedEdge) {
    return (
      <div className="flex h-full w-[260px] flex-col items-center justify-center border-l border-default bg-sidebar px-6">
        <div className="mb-3 flex h-9 w-9 items-center justify-center rounded-lg border border-default bg-elevated text-muted-foreground">
          <MousePointer size={15} />
        </div>
        <p className="text-center text-xs font-medium text-muted-foreground">
          Select a device or connection
        </p>
        <p className="mt-1 text-center text-[10px] text-muted-foreground/50 leading-relaxed">
          Properties appear here. Hover a device to see a quick summary.
        </p>
      </div>
    )
  }

  if (selectedEdge) {
    const edgeData = (selectedEdge.data || {}) as Record<string, unknown>
    const connectionType = (edgeData.connectionType as string) || 'ethernet'
    const isCustomType = !CONNECTION_TYPE_OPTIONS.includes(connectionType as typeof CONNECTION_TYPE_OPTIONS[number])

    return (
      <div className="flex h-full w-[260px] flex-col border-l border-default bg-sidebar">
        <div className="border-b border-default px-3 py-2">
          <h3 className="text-xs font-semibold text-heading">Connection</h3>
        </div>
        <div className="flex flex-1 flex-col gap-3 overflow-y-auto p-3">
          <div className="rounded border border-default bg-elevated/40 px-2.5 py-2 text-[10px] text-muted-foreground">
            Drag either end of the line on the canvas to reconnect it to a different asset.
          </div>
          <div className="flex flex-col gap-1">
            <FieldLabel>Label</FieldLabel>
            <FieldInput
              value={(selectedEdge.label as string) || ''}
              onChange={val => onEdgeUpdate(selectedEdge.id, { label: val || null })}
              placeholder="Connection label"
            />
          </div>
          <div className="flex flex-col gap-1">
            <FieldLabel>Type</FieldLabel>
            <select
              value={isCustomType ? '__custom__' : connectionType}
              onChange={e => {
                const val = e.target.value
                if (val !== '__custom__') {
                  onEdgeUpdate(selectedEdge.id, { connectionType: val })
                }
              }}
              className="w-full rounded border border-default bg-input px-2 py-1.5 text-xs text-primary focus:border-accent focus:outline-none"
            >
              {CONNECTION_TYPE_OPTIONS.map(opt => (
                <option key={opt} value={opt}>{opt.charAt(0).toUpperCase() + opt.slice(1)}</option>
              ))}
              <option value="__custom__">Custom…</option>
            </select>
            {isCustomType && (
              <FieldInput
                value={connectionType}
                onChange={val => onEdgeUpdate(selectedEdge.id, { connectionType: val })}
                placeholder="Custom type name"
              />
            )}
          </div>
          <div className="flex flex-col gap-1">
            <FieldLabel>Speed</FieldLabel>
            <FieldInput
              value={(edgeData.speed as string) || ''}
              onChange={val => onEdgeUpdate(selectedEdge.id, { speed: val || null })}
              placeholder="e.g. 1 Gbps"
            />
          </div>
          <div className="flex flex-col gap-1">
            <FieldLabel>Notes</FieldLabel>
            <FieldInput
              value={(edgeData.notes as string) || ''}
              onChange={val => onEdgeUpdate(selectedEdge.id, { notes: val || null })}
              placeholder="Port info, cable type…"
              mono
            />
          </div>
          <div className="flex flex-col gap-1">
            <FieldLabel>Line Style</FieldLabel>
            <div className="flex gap-1">
              {([
                { value: null, icon: Minus, label: 'Straight' },
                { value: 'curved', icon: Spline, label: 'Curved' },
                { value: 'step', icon: GitBranch, label: 'Step' },
                { value: 'orthogonal', icon: CornerUpRight, label: 'Ortho' },
              ] as const).map(({ value, icon: Icon, label }) => {
                const routing = (edgeData.routing as string | null | undefined) ?? null
                const active = routing === value
                return (
                  <button
                    key={label}
                    title={label}
                    onClick={() => onEdgeUpdate(selectedEdge.id, { routing: value })}
                    className={cn(
                      'flex flex-1 items-center justify-center gap-1 rounded border py-1.5 text-[10px] transition-colors',
                      active
                        ? 'border-accent bg-accent/10 text-accent'
                        : 'border-default text-muted-foreground hover:border-hover hover:text-primary',
                    )}
                  >
                    <Icon size={12} />
                    {label}
                  </button>
                )
              })}
            </div>
          </div>
          <div className="flex items-center justify-between">
            <FieldLabel>Show Traffic</FieldLabel>
            <button
              onClick={() => {
                const newType = selectedEdge.type === 'animated' ? 'connection' : 'animated'
                onEdgeTypeChange(selectedEdge.id, newType)
              }}
              className={cn(
                'relative h-5 w-9 rounded-full transition-colors',
                selectedEdge.type === 'animated' ? 'bg-accent' : 'bg-elevated',
              )}
            >
              <span
                className={cn(
                  'absolute top-0.5 left-0.5 h-4 w-4 rounded-full bg-white transition-transform',
                  selectedEdge.type === 'animated' && 'translate-x-4',
                )}
              />
            </button>
          </div>
        </div>
        <div className="border-t border-default p-3">
          {deleteConfirm ? (
            <div className="flex flex-col gap-1.5">
              <p className="text-center text-[10px] text-muted-foreground">Delete this connection?</p>
              <div className="flex gap-1.5">
                <button
                  onClick={() => setDeleteConfirm(false)}
                  className="flex-1 rounded border border-default px-2 py-1.5 text-xs text-primary hover:bg-elevated"
                >
                  Cancel
                </button>
                <button
                  onClick={() => onDeleteEdge(selectedEdge.id)}
                  className="flex-1 rounded bg-red-500/20 px-2 py-1.5 text-xs font-medium text-red-400 hover:bg-red-500/30"
                >
                  Delete
                </button>
              </div>
            </div>
          ) : (
            <button
              onClick={() => setDeleteConfirm(true)}
              className="flex w-full items-center justify-center gap-1.5 rounded border border-red-500/30 px-2 py-1.5 text-xs text-red-400 hover:bg-red-500/10"
            >
              <Trash2 size={12} />
              Delete Connection
            </button>
          )}
        </div>
      </div>
    )
  }

  const nodeData = selectedNode!.data as unknown as DeviceNodeData
  const props = nodeData.properties || {} as DeviceProperties
  const currentStatus = (props.status || 'unknown') as NodeStatus

  return (
    <div className="flex h-full w-[260px] flex-col border-l border-default bg-sidebar">
      <div className="border-b border-default px-3 py-2">
        <h3 className="text-xs font-semibold text-heading">Device Properties</h3>
      </div>

      <div className="flex flex-1 flex-col gap-3 overflow-y-auto p-3">

        {/* Identity */}
        <div className="flex flex-col gap-1">
          <FieldLabel>Name</FieldLabel>
          <FieldInput value={nodeData.label} onChange={handleLabelChange} placeholder="Device name" />
        </div>

        {/* Layering */}
        <div className="flex flex-col gap-1">
          <FieldLabel>Layer</FieldLabel>
          <div className="flex gap-1.5">
            <button
              onClick={() => onBringToFront(selectedNode!.id)}
              title="Bring to Front  ]"
              className="flex flex-1 items-center justify-center gap-1.5 rounded border border-default px-2 py-1.5 text-[10px] text-muted-foreground hover:border-hover hover:text-primary"
            >
              <BringToFront size={12} />
              Bring Front
            </button>
            <button
              onClick={() => onSendToBack(selectedNode!.id)}
              title="Send to Back  ["
              className="flex flex-1 items-center justify-center gap-1.5 rounded border border-default px-2 py-1.5 text-[10px] text-muted-foreground hover:border-hover hover:text-primary"
            >
              <SendToBack size={12} />
              Send Back
            </button>
          </div>
        </div>

        {/* Status badge grid */}
        <div className="flex flex-col gap-1.5">
          <FieldLabel>Status</FieldLabel>
          <div className="grid grid-cols-2 gap-1">
            {STATUS_OPTIONS.map(opt => {
              const { color, label } = STATUS_CONFIG[opt]
              const active = currentStatus === opt
              return (
                <button
                  key={opt}
                  onClick={() => handlePropertyChange('status', opt)}
                  className={cn(
                    'flex items-center justify-center gap-1.5 rounded border py-1.5 text-[10px] font-medium transition-colors',
                    active
                      ? 'border-transparent text-white'
                      : 'border-default text-muted-foreground hover:border-hover hover:text-primary',
                  )}
                  style={active ? { backgroundColor: color } : undefined}
                >
                  <span
                    className="h-1.5 w-1.5 shrink-0 rounded-full"
                    style={{ backgroundColor: active ? 'rgba(255,255,255,0.8)' : color }}
                  />
                  {label}
                </button>
              )
            })}
          </div>
        </div>

        {/* Network section */}
        <SectionDivider label="Network" />
        <div className="flex flex-col gap-2">
          <div className="flex flex-col gap-1">
            <FieldLabel>IP Address</FieldLabel>
            <FieldInput value={props.ip || ''} onChange={v => handlePropertyChange('ip', v)} placeholder="e.g. 10.0.0.1" mono />
          </div>
          <div className="flex flex-col gap-1">
            <FieldLabel>Subnet</FieldLabel>
            <FieldInput value={props.subnet || ''} onChange={v => handlePropertyChange('subnet', v)} placeholder="e.g. 10.0.0.0/24" mono />
          </div>
          <div className="flex flex-col gap-1">
            <FieldLabel>VLAN</FieldLabel>
            <FieldInput value={props.vlan || ''} onChange={v => handlePropertyChange('vlan', v)} placeholder="e.g. 10" mono />
          </div>
        </div>

        {/* Hardware section */}
        <SectionDivider label="Hardware" />
        <div className="flex flex-col gap-2">
          <div className="flex flex-col gap-1">
            <FieldLabel>Hostname</FieldLabel>
            <FieldInput value={props.hostname || ''} onChange={v => handlePropertyChange('hostname', v)} placeholder="e.g. core-rtr-01" mono />
          </div>
          <div className="flex flex-col gap-1">
            <FieldLabel>Vendor</FieldLabel>
            <FieldInput value={props.vendor || ''} onChange={v => handlePropertyChange('vendor', v)} placeholder="e.g. Cisco" />
          </div>
          <div className="flex flex-col gap-1">
            <FieldLabel>Model</FieldLabel>
            <FieldInput value={props.model || ''} onChange={v => handlePropertyChange('model', v)} placeholder="e.g. ISR 4331" />
          </div>
          <div className="flex flex-col gap-1">
            <FieldLabel>Role</FieldLabel>
            <FieldInput value={props.role || ''} onChange={v => handlePropertyChange('role', v)} placeholder="e.g. Core gateway" />
          </div>
        </div>

        {/* Notes */}
        <SectionDivider label="Notes" />
        <div className="flex flex-col gap-1">
          <textarea
            value={props.notes || ''}
            onChange={e => handlePropertyChange('notes', e.target.value)}
            placeholder="Additional notes…"
            rows={3}
            className="w-full resize-none rounded border border-default bg-input px-2 py-1.5 text-xs text-primary placeholder:text-muted-foreground focus:border-accent focus:outline-none"
          />
        </div>

      </div>

      <div className="border-t border-default p-3">
        {deleteConfirm ? (
          <div className="flex flex-col gap-1.5">
            <p className="text-center text-[10px] text-muted-foreground">Delete this device?</p>
            <div className="flex gap-1.5">
              <button
                onClick={() => setDeleteConfirm(false)}
                className="flex-1 rounded border border-default px-2 py-1.5 text-xs text-primary hover:bg-elevated"
              >
                Cancel
              </button>
              <button
                onClick={() => onDeleteNode(selectedNode!.id)}
                className="flex-1 rounded bg-red-500/20 px-2 py-1.5 text-xs font-medium text-red-400 hover:bg-red-500/30"
              >
                Delete
              </button>
            </div>
          </div>
        ) : (
          <button
            onClick={() => setDeleteConfirm(true)}
            className="flex w-full items-center justify-center gap-1.5 rounded border border-red-500/30 px-2 py-1.5 text-xs text-red-400 hover:bg-red-500/10"
          >
            <Trash2 size={12} />
            Delete Device
          </button>
        )}
      </div>
    </div>
  )
}
