// frontend/src/modals/crm/helpdesk/EntryFormModal.jsx
// Create or edit a Note or Issue entry.
// When editing, the type is locked. defaultType prop seeds the type on creation.

import { useState, useEffect, useRef, useCallback } from 'react'
import { createPortal } from 'react-dom'
import api from '@/lib/api'
import { useAuth } from '@/hooks/useAuth'
import { useToast } from '@/components/ui/Toast'
import Modal from '@/components/ui/Modal'
import Button from '@/components/ui/Button'
import FormField from '@/components/ui/FormField'
import Spinner from '@/components/ui/Spinner'
import DateTimePicker from '@/components/ui/DateTimePicker'

// ─── Constants ────────────────────────────────────────────────────────────────

const STATUS_OPTIONS = [
  { value: 'open',        label: 'Open'        },
  { value: 'researching', label: 'Researching' },
  { value: 'resolved',    label: 'Resolved'    },
]

const SEVERITY_OPTIONS = [
  { value: 'low',      label: 'Low'      },
  { value: 'medium',   label: 'Medium'   },
  { value: 'high',     label: 'High'     },
  { value: 'critical', label: 'Critical' },
]

const CATEGORY_OPTIONS = [
  { value: 'technical',       label: 'Technical Issue'  },
  { value: 'install_support', label: 'Install Support'  },
  { value: 'general',         label: 'General'          },
]

const ENTITY_TYPES = [
  { value: 'device',   label: 'Device'   },
  { value: 'app_user', label: 'App User' },
  { value: 'customer', label: 'Customer' },
]

// ─── Entity search helpers ────────────────────────────────────────────────────

// Returns { primary, secondary } lines for a result item
// Field names from actual API responses:
//   device:   device_name, serial_number, hw_family/hw_revision
//   app_user: display_name, email
//   customer: name, surname, organization, location.city
function entityLines(type, item) {
  if (type === 'device') {
    return {
      primary:   item.device_name || item.id,
      secondary: item.serial_number || '',
    }
  }
  if (type === 'app_user') {
    return {
      primary:   item.display_name || item.email || item.id,
      secondary: item.email || '',
    }
  }
  if (type === 'customer') {
    const primary   = [item.surname, item.name].filter(Boolean).join(' ') || item.id
    const city      = item.location?.city || item.city || ''
    const secondary = [item.organization, city].filter(Boolean).join(' · ')
    return { primary, secondary }
  }
  return { primary: item.id, secondary: '' }
}

// Returns the chip display text for a picked entity
function entityDisplayName(type, item) {
  if (type === 'device')   return item.device_name || item.id
  if (type === 'app_user') return item.display_name || item.email || item.id
  if (type === 'customer') return [item.surname, item.name].filter(Boolean).join(' ') || item.id
  return item.id
}

// ─── EntitySearchInput ────────────────────────────────────────────────────────
// Inline search box + dropdown for a single entity type.
// Dropdown is rendered via portal so it's never clipped by a parent modal.

function EntitySearchInput({ entityType, value, displayName, onChange, onBrowse, locked }) {
  const [query,     setQuery]     = useState('')
  const [results,   setResults]   = useState([])
  const [searching, setSearching] = useState(false)
  const [open,      setOpen]      = useState(false)
  const [dropPos,   setDropPos]   = useState({ top: 0, left: 0, width: 0 })
  const debounceRef  = useRef(null)
  const wrapRef      = useRef(null)
  const inputWrapRef = useRef(null)
  const dropRef      = useRef(null)

  // Close dropdown on outside click — must check both the input wrapper AND the portal dropdown
  useEffect(() => {
    const handler = (e) => {
      const inWrap = wrapRef.current && wrapRef.current.contains(e.target)
      const inDrop = dropRef.current && dropRef.current.contains(e.target)
      if (!inWrap && !inDrop) setOpen(false)
    }
    document.addEventListener('mousedown', handler)
    return () => document.removeEventListener('mousedown', handler)
  }, [])

  // When the selected value changes externally, clear the query
  useEffect(() => { setQuery('') }, [value])

  const updateDropPos = () => {
    if (inputWrapRef.current) {
      const r = inputWrapRef.current.getBoundingClientRect()
      setDropPos({ top: r.bottom + 4, left: r.left, width: r.width })
    }
  }

  const search = useCallback(async (q) => {
    if (!q.trim()) { setResults([]); setOpen(false); return }
    setSearching(true)
    try {
      let data
      if (entityType === 'device') {
        data = await api.get(`/devices?search=${encodeURIComponent(q)}&limit=8`)
        setResults(data.devices || data.data || [])
      } else if (entityType === 'app_user') {
        data = await api.get(`/users?search=${encodeURIComponent(q)}&limit=8`)
        setResults(data.users || data.data || [])
      } else if (entityType === 'customer') {
        data = await api.get(`/crm/customers?search=${encodeURIComponent(q)}&limit=8`)
        setResults(data.customers || data.data || [])
      }
      updateDropPos()
      setOpen(true)
    } catch { /* silent */ } finally {
      setSearching(false)
    }
  }, [entityType])

  const handleInput = (e) => {
    const q = e.target.value
    setQuery(q)
    if (!q.trim()) { onChange(null); setResults([]); setOpen(false); return }
    clearTimeout(debounceRef.current)
    debounceRef.current = setTimeout(() => search(q), 280)
  }

  const pick = (item) => {
    onChange({ id: item.id, displayName: entityDisplayName(entityType, item) })
    setQuery('')
    setResults([])
    setOpen(false)
  }

  const clear = () => { onChange(null); setQuery(''); setResults([]); setOpen(false) }

  const placeholder = {
    device:   'Search by name or serial…',
    app_user: 'Search by name or email…',
    customer: 'Search by name, email, phone, org…',
  }[entityType] || 'Search…'

  return (
    <div ref={wrapRef} style={{ flex: 1, minWidth: 0 }}>
      {/* Input row — styled like .input */}
      <div
        ref={inputWrapRef}
        className="input"
        style={{
          display: 'flex', alignItems: 'center',
          padding: 0,
          overflow: 'hidden',
          cursor: 'text',
        }}
        onFocusCapture={e => e.currentTarget.style.borderColor = 'var(--color-primary)'}
        onBlurCapture={e => e.currentTarget.style.borderColor = ''}
      >
        {/* Selected chip OR text input */}
        {value && displayName ? (
          <div style={{ flex: 1, display: 'flex', alignItems: 'center', gap: 'var(--space-2)', padding: 'var(--space-3) var(--space-4)', minWidth: 0 }}>
            <span style={{
              fontSize: 'var(--font-size-base)', color: 'var(--color-text-primary)',
              overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1,
            }}>
              {displayName}
            </span>
            {!locked && (
              <button
                onClick={clear}
                style={{ flexShrink: 0, background: 'none', border: 'none', cursor: 'pointer', color: 'var(--color-text-muted)', padding: '2px', lineHeight: 1, fontSize: 14, display: 'flex', alignItems: 'center' }}
                title="Clear"
              >
                ×
              </button>
            )}
          </div>
        ) : locked ? (
          /* locked but no value yet — show empty disabled state */
          <div style={{ flex: 1, padding: 'var(--space-3) var(--space-4)', color: 'var(--color-text-muted)', fontSize: 'var(--font-size-sm)' }}>
            —
          </div>
        ) : (
          <input
            type="text"
            value={query}
            onChange={handleInput}
            placeholder={placeholder}
            style={{
              flex: 1, border: 'none', outline: 'none',
              background: 'transparent',
              padding: 'var(--space-3) var(--space-4)',
              fontSize: 'var(--font-size-base)',
              color: 'var(--color-text-primary)',
              fontFamily: 'var(--font-family-base)',
              lineHeight: 'var(--line-height-base)',
            }}
          />
        )}

        {/* Spinner */}
        {searching && (
          <div style={{ padding: '0 var(--space-2)', display: 'flex', alignItems: 'center' }}>
            <Spinner size="xs" />
          </div>
        )}

        {/* Browse magnifying glass — hidden when locked */}
        {!locked && (
          <button
            onClick={onBrowse}
            title={`Browse all ${entityType === 'app_user' ? 'users' : entityType + 's'}`}
            style={{
              flexShrink: 0, padding: 'var(--space-2) var(--space-3)',
              background: 'none', border: 'none',
              borderLeft: '1px solid var(--color-border)',
              cursor: 'pointer',
              color: 'var(--color-text-muted)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              transition: 'color 0.1s, background 0.1s',
              alignSelf: 'stretch',
            }}
            onMouseEnter={e => { e.currentTarget.style.color = 'var(--color-primary)'; e.currentTarget.style.background = 'var(--color-primary-subtle)' }}
            onMouseLeave={e => { e.currentTarget.style.color = 'var(--color-text-muted)'; e.currentTarget.style.background = 'none' }}
          >
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <circle cx="11" cy="11" r="8"/>
              <line x1="21" y1="21" x2="16.65" y2="16.65"/>
            </svg>
          </button>
        )}
      </div>

      {/* Dropdown — rendered via portal so it's never clipped by the modal */}
      {open && results.length > 0 && createPortal(
        <div ref={dropRef} style={{
          position: 'fixed',
          top: dropPos.top, left: dropPos.left, width: dropPos.width,
          zIndex: 9999,
          backgroundColor: 'var(--color-bg-elevated)',
          border: '1px solid var(--color-border)',
          borderRadius: 'var(--radius-lg)',
          boxShadow: 'var(--shadow-lg)',
          overflow: 'hidden',
          maxHeight: 260,
          overflowY: 'auto',
        }}>
          {results.map((item, i) => {
            const lines = entityLines(entityType, item)
            return (
              <button
                key={item.id || i}
                onClick={() => pick(item)}
                style={{
                  display: 'block', width: '100%', textAlign: 'left',
                  padding: 'var(--space-3) var(--space-4)',
                  background: 'none', border: 'none', cursor: 'pointer',
                  borderBottom: i < results.length - 1 ? '1px solid var(--color-border)' : 'none',
                  transition: 'background 0.1s',
                }}
                onMouseEnter={e => e.currentTarget.style.background = 'var(--color-bg-island)'}
                onMouseLeave={e => e.currentTarget.style.background = 'none'}
              >
                <p style={{ margin: 0, fontWeight: 'var(--font-weight-medium)', color: 'var(--color-text-primary)', fontSize: 'var(--font-size-sm)' }}>
                  {lines.primary}
                </p>
                {lines.secondary && (
                  <p style={{ margin: 0, color: 'var(--color-text-muted)', fontSize: 'var(--font-size-xs)' }}>
                    {lines.secondary}
                  </p>
                )}
              </button>
            )
          })}
        </div>,
        document.body
      )}
    </div>
  )
}

// ─── EntityBrowseModal ────────────────────────────────────────────────────────
// Full-list picker modal opened by the magnifying glass button.

function EntityBrowseModal({ open, entityType, onPick, onClose }) {
  const [items,    setItems]    = useState([])
  const [loading,  setLoading]  = useState(false)
  const [search,   setSearch]   = useState('')
  const debounceRef = useRef(null)

  const load = useCallback(async (q = '') => {
    setLoading(true)
    try {
      let data
      const qs = q ? `?search=${encodeURIComponent(q)}&limit=50` : '?limit=50'
      if (entityType === 'device') {
        data = await api.get(`/devices${qs}`)
        setItems(data.devices || data.data || [])
      } else if (entityType === 'app_user') {
        data = await api.get(`/users${qs}`)
        setItems(data.users || data.data || [])
      } else if (entityType === 'customer') {
        data = await api.get(`/crm/customers${qs}`)
        setItems(data.customers || data.data || [])
      }
    } catch { /* silent */ } finally {
      setLoading(false)
    }
  }, [entityType])

  useEffect(() => { if (open) { setSearch(''); load() } }, [open, load])

  const handleSearch = (e) => {
    const q = e.target.value
    setSearch(q)
    clearTimeout(debounceRef.current)
    debounceRef.current = setTimeout(() => load(q), 300)
  }

  const typeLabel = { device: 'Devices', app_user: 'Users', customer: 'Customers' }[entityType] || entityType

  // Two-line row renderer consistent with inline dropdown
  const renderRow = (item) => {
    const lines = entityLines(entityType, item)
    return (
      <div style={{ minWidth: 0 }}>
        <p style={{ margin: 0, fontWeight: 'var(--font-weight-medium)', color: 'var(--color-text-primary)', fontSize: 'var(--font-size-sm)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
          {lines.primary || '—'}
        </p>
        {lines.secondary && (
          <p style={{ margin: 0, color: 'var(--color-text-muted)', fontSize: 'var(--font-size-xs)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {lines.secondary}
          </p>
        )}
      </div>
    )
  }

  return (
    <Modal open={open} onClose={onClose} title={`Select ${typeLabel.slice(0, -1)}`} size="md">
      <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-4)' }}>
        {/* Search */}
        <input
          type="text"
          value={search}
          onChange={handleSearch}
          placeholder={`Search ${typeLabel.toLowerCase()}…`}
          autoFocus
          className="input"
          style={{ boxSizing: 'border-box' }}
        />

        {/* List */}
        <div style={{
          border: '1px solid var(--color-border)',
          borderRadius: 'var(--radius-lg)',
          overflow: 'hidden',
          maxHeight: 360,
          overflowY: 'auto',
        }}>
          {loading ? (
            <div style={{ display: 'flex', justifyContent: 'center', padding: 'var(--space-8)' }}><Spinner size="sm" /></div>
          ) : items.length === 0 ? (
            <div style={{ padding: 'var(--space-8)', textAlign: 'center', color: 'var(--color-text-muted)', fontSize: 'var(--font-size-sm)' }}>
              No {typeLabel.toLowerCase()} found.
            </div>
          ) : (
            items.map((item, i) => (
              <button
                key={item.id || i}
                onClick={() => { onPick({ id: item.id, displayName: entityDisplayName(entityType, item) }); onClose() }}
                style={{
                  display: 'flex', width: '100%', textAlign: 'left',
                  padding: 'var(--space-3) var(--space-4)',
                  background: 'none', border: 'none', cursor: 'pointer',
                  borderBottom: i < items.length - 1 ? '1px solid var(--color-border)' : 'none',
                  transition: 'background 0.1s',
                }}
                onMouseEnter={e => e.currentTarget.style.background = 'var(--color-bg-island)'}
                onMouseLeave={e => e.currentTarget.style.background = 'none'}
              >
                {renderRow(item)}
              </button>
            ))
          )}
        </div>
      </div>
    </Modal>
  )
}

// ─── Empty link row ───────────────────────────────────────────────────────────

const emptyLink = () => ({ _key: Math.random(), entity_type: 'device', entity_id: '', _displayName: '', _locked: false })

// ─── EntryFormModal ───────────────────────────────────────────────────────────

export default function EntryFormModal({
  open,
  entry,          // null = create mode, object = edit mode
  defaultType,    // 'note' | 'issue' — used in create mode only
  prefilledLinks, // [{entity_type, entity_id, display_name, locked}] — used when opened from an entity detail page
  knownEntities,  // {[entity_id]: display_name} — used to resolve display names in edit mode
  onClose,
  onSaved,
  onDelete,
}) {
  const { user } = useAuth()
  const { toast } = useToast()

  const isEdit = !!entry
  const entryType = isEdit ? entry.type : (defaultType || 'issue')

  const [form, setForm] = useState({
    type:      entryType,
    title:     '',
    body:      '',
    status:    'open',
    severity:  '',
    category:  '',
    occurred_at: new Date().toISOString(),
  })
  const [links,   setLinks]   = useState([emptyLink()])
  const [saving,  setSaving]  = useState(false)
  const [error,   setError]   = useState('')

  // Browse modal state
  const [browseLink, setBrowseLink] = useState(null) // { key, entityType }

  // Seed form when modal opens
  useEffect(() => {
    if (!open) return
    if (isEdit) {
      setForm({
        type:        entry.type,
        title:       entry.title || '',
        body:        entry.body  || '',
        status:      entry.status    || 'open',
        severity:    entry.severity  || '',
        category:    entry.category  || '',
        occurred_at: entry.occurred_at || new Date().toISOString(),
      })
      setLinks(
        (entry.links || []).length > 0
          ? entry.links.map(l => {
              // Resolve display name: prefer API-returned name, then caller-supplied knownEntities lookup, then fall back to raw ID
              const resolved = l.display_name || (knownEntities && knownEntities[l.entity_id]) || l.entity_id
              // Mark as locked if it matches a prefilled entity
              const isLocked = prefilledLinks
                ? prefilledLinks.some(p => p.entity_id === l.entity_id && p.locked)
                : false
              return {
                _key: Math.random(),
                entity_type: l.entity_type,
                entity_id: l.entity_id,
                _displayName: resolved,
                _locked: isLocked,
              }
            })
          : [emptyLink()]
      )
    } else {
      setForm({
        type:        entryType,
        title:       '',
        body:        '',
        status:      'open',
        severity:    '',
        category:    '',
        occurred_at: new Date().toISOString(),
      })
      setLinks(
        prefilledLinks && prefilledLinks.length > 0
          ? prefilledLinks.map(l => ({ _key: Math.random(), ...l, _displayName: l.display_name || l.entity_id || '', _locked: !!l.locked }))
          : [emptyLink()]
      )
    }
    setError('')
    setBrowseLink(null)
  }, [open, entry, entryType, isEdit, prefilledLinks, knownEntities])

  const set = (field) => (e) => setForm(prev => ({ ...prev, [field]: e.target.value }))

  // ── Links management ──
  const addLink    = () => setLinks(prev => [...prev, emptyLink()])
  const removeLink = (key) => setLinks(prev => prev.filter(l => l._key !== key))
  const updateLinkType = (key, newType) =>
    setLinks(prev => prev.map(l => l._key === key ? { ...l, entity_type: newType, entity_id: '', _displayName: '' } : l))
  const updateLinkEntity = (key, picked) =>
    setLinks(prev => prev.map(l => l._key === key
      ? { ...l, entity_id: picked ? picked.id : '', _displayName: picked ? picked.displayName : '' }
      : l
    ))

  const isIssue = form.type === 'issue'

  // ── Save ──
  const save = async () => {
    if (!form.title.trim()) { setError('Title is required.'); return }
    if (isIssue && !form.status) { setError('Status is required for issues.'); return }

    const validLinks = links.filter(l => l.entity_id.trim())

    const payload = {
      type:        form.type,
      title:       form.title.trim(),
      body:        form.body.trim() || null,
      status:      isIssue ? form.status   : null,
      severity:    isIssue ? form.severity || null : null,
      category:    isIssue ? form.category || null : null,
      occurred_at: form.occurred_at || null,
      links:       validLinks.map(l => ({ entity_type: l.entity_type, entity_id: l.entity_id.trim() })),
    }

    setSaving(true)
    setError('')
    try {
      if (isEdit) {
        await api.patch(`/notes/${entry.id}`, {
          title:       payload.title,
          body:        payload.body,
          status:      payload.status,
          severity:    payload.severity,
          category:    payload.category,
          occurred_at: payload.occurred_at,
        })
        await api.patch(`/notes/${entry.id}/links`, { links: payload.links })
      } else {
        await api.post('/notes', payload)
      }
      toast.success(isEdit ? 'Updated' : 'Created', `${isIssue ? 'Issue' : 'Note'} saved successfully.`)
      onSaved()
    } catch (err) {
      setError(err.message || 'Save failed.')
    } finally {
      setSaving(false)
    }
  }

  const title = isEdit
    ? `Edit ${isIssue ? 'Issue' : 'Note'}`
    : `New ${entryType === 'issue' ? 'Issue' : 'Note'}`

  return (
    <>
      <Modal
        open={open}
        onClose={onClose}
        title={title}
        size="lg"
        footer={
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%' }}>
            <div>
              {isEdit && onDelete && (
                <Button variant="danger" size="sm" onClick={() => onDelete(entry.id)}>
                  Delete
                </Button>
              )}
            </div>
            <div style={{ display: 'flex', gap: 'var(--space-3)' }}>
              <Button variant="secondary" size="md" onClick={onClose}>Cancel</Button>
              <Button variant="primary" size="md" onClick={save} loading={saving}>
                {isEdit ? 'Save Changes' : `Create ${isIssue ? 'Issue' : 'Note'}`}
              </Button>
            </div>
          </div>
        }
      >
        <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-5)' }}>
          {error && (
            <div style={{
              padding: 'var(--space-3) var(--space-4)',
              backgroundColor: 'var(--color-danger-bg)',
              border: '1px solid var(--color-danger)',
              borderRadius: 'var(--radius-md)',
              color: 'var(--color-danger)',
              fontSize: 'var(--font-size-sm)',
            }}>
              {error}
            </div>
          )}

          {/* Title (70%) + DateTime (30%) on the same row */}
          <div style={{ display: 'grid', gridTemplateColumns: '7fr 3fr', gap: 'var(--space-4)' }}>
            <FormField
              label="Title"
              name="title"
              type="text"
              value={form.title}
              onChange={set('title')}
              placeholder={isIssue ? 'Brief description of the issue…' : 'Note title…'}
              required
            />
            <DateTimePicker
              label="Date & Time"
              name="occurred_at"
              value={form.occurred_at}
              onChange={(iso) => setForm(prev => ({ ...prev, occurred_at: iso }))}
            />
          </div>

          {/* Issue-only fields */}
          {isIssue && (
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 'var(--space-4)' }}>
              <FormField label="Status" name="status" type="select" value={form.status} onChange={set('status')}>
                {STATUS_OPTIONS.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
              </FormField>

              <FormField label="Severity" name="severity" type="select" value={form.severity} onChange={set('severity')}>
                <option value="">No severity</option>
                {SEVERITY_OPTIONS.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
              </FormField>

              <FormField label="Category" name="category" type="select" value={form.category} onChange={set('category')}>
                <option value="">No category</option>
                {CATEGORY_OPTIONS.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
              </FormField>
            </div>
          )}

          {/* Body */}
          <FormField
            label="Description"
            name="body"
            type="textarea"
            value={form.body}
            onChange={set('body')}
            placeholder="Detailed description, steps to reproduce, observations…"
            rows={5}
          />

          {/* Entity links — reworked */}
          <div>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 'var(--space-3)' }}>
              <label style={{ fontSize: 'var(--font-size-sm)', fontWeight: 'var(--font-weight-semibold)', color: 'var(--color-text-secondary)' }}>
                Linked Entities
                <span style={{ fontWeight: 'var(--font-weight-normal)', color: 'var(--color-text-muted)', marginLeft: 'var(--space-2)' }}>
                  (optional)
                </span>
              </label>
              <Button variant="ghost" size="sm" onClick={addLink}>+ Add link</Button>
            </div>

            <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-2)' }}>
              {links.map((link) => (
                <div key={link._key} style={{ display: 'grid', gridTemplateColumns: '140px 1fr auto', gap: 'var(--space-3)', alignItems: 'center' }}>
                  {/* Type selector — locked when the link is a prefilled entity */}
                  {link._locked ? (
                    <div style={{
                      padding: 'var(--space-3) var(--space-4)',
                      border: '1px solid var(--color-border)',
                      borderRadius: 'var(--radius-md)',
                      fontSize: 'var(--font-size-base)',
                      color: 'var(--color-text-muted)',
                      background: 'var(--color-bg-abyss)',
                    }}>
                      {ENTITY_TYPES.find(t => t.value === link.entity_type)?.label || link.entity_type}
                    </div>
                  ) : (
                    <FormField
                      name={`link_type_${link._key}`}
                      type="select"
                      value={link.entity_type}
                      onChange={e => updateLinkType(link._key, e.target.value)}
                      label=""
                    >
                      {ENTITY_TYPES.map(t => <option key={t.value} value={t.value}>{t.label}</option>)}
                    </FormField>
                  )}

                  {/* Entity search input */}
                  <EntitySearchInput
                    entityType={link.entity_type}
                    value={link.entity_id}
                    displayName={link._displayName}
                    onChange={(picked) => updateLinkEntity(link._key, picked)}
                    onBrowse={() => setBrowseLink({ key: link._key, entityType: link.entity_type })}
                    locked={link._locked}
                  />

                  {/* Remove — hidden for locked links */}
                  {link._locked ? (
                    <div style={{ width: 28 }} />
                  ) : (
                    <button
                      onClick={() => removeLink(link._key)}
                      style={{
                        width: 28, height: 28,
                        display: 'flex', alignItems: 'center', justifyContent: 'center',
                        borderRadius: 'var(--radius-md)',
                        border: 'none',
                        backgroundColor: 'transparent',
                        color: 'var(--color-text-muted)',
                        cursor: 'pointer',
                        fontSize: 16,
                        lineHeight: 1,
                        flexShrink: 0,
                      }}
                      title="Remove link"
                    >
                      ×
                    </button>
                  )}
                </div>
              ))}
            </div>
          </div>
        </div>
      </Modal>

      {/* Browse-all picker — rendered outside the main modal to avoid z-index stacking */}
      {browseLink && (
        <EntityBrowseModal
          open
          entityType={browseLink.entityType}
          onPick={(picked) => { updateLinkEntity(browseLink.key, picked); setBrowseLink(null) }}
          onClose={() => setBrowseLink(null)}
        />
      )}
    </>
  )
}
