import React, { useState } from 'react'
import { saveEntryMeta } from '../api'

// §22.4a SLICE-4 (PUC-1, UX §5.2): a schema-driven view/edit panel for one
// entry's metadata. One control per declared field — enum → single-select,
// tags → removable chips + add-input, text → text input. Authorized users
// (canEdit) save changed values via a direct sidecar commit; the document body
// renders separately as pure prose. A collection with no `fields` renders
// nothing (INV-5: today's behavior unchanged).

const labelFor = (name, def) =>
  def?.label || name.charAt(0).toUpperCase() + name.slice(1)

const sameValue = (a, b) => JSON.stringify(a ?? null) === JSON.stringify(b ?? null)

export default function MetadataFieldsPanel({
  projectId, collectionId, slug, fields, meta, canEdit,
}) {
  const [draft, setDraft] = useState(() => ({ ...(meta || {}) }))
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState(null)
  const [saved, setSaved] = useState(false)
  const [tagInput, setTagInput] = useState('')

  if (!fields || Object.keys(fields).length === 0) return null

  const setField = (name, value) => {
    setSaved(false)
    setDraft(d => ({ ...d, [name]: value }))
  }

  const changedFields = Object.keys(fields).filter(
    n => !sameValue(draft[n], (meta || {})[n]))
  const changed = changedFields.length > 0

  const onSave = async () => {
    setSaving(true); setError(null); setSaved(false)
    const values = {}
    for (const n of changedFields) values[n] = draft[n]
    try {
      await saveEntryMeta(projectId, collectionId, slug, values)
      setSaved(true)
    } catch (e) {
      setError(e.message || 'Could not save metadata')
    } finally {
      setSaving(false)
    }
  }

  return (
    <div className="metadata-fields-panel">
      {Object.entries(fields).map(([name, def]) => (
        <div key={name} className="metadata-field">
          <label htmlFor={`mf-${name}`}>{labelFor(name, def)}</label>
          {!canEdit ? (
            <ReadOnlyValue type={def.type} value={draft[name]} />
          ) : def.type === 'enum' ? (
            <select id={`mf-${name}`} value={draft[name] ?? ''}
              onChange={e => setField(name, e.target.value || null)}>
              <option value="">—</option>
              {(def.values || []).map(v => <option key={v} value={v}>{v}</option>)}
            </select>
          ) : def.type === 'tags' ? (
            <div className="tags-edit">
              {(draft[name] || []).map(t => (
                <span key={t} className="tag-chip">
                  {t}
                  <button type="button" aria-label={`remove ${t}`}
                    onClick={() => setField(name, (draft[name] || []).filter(x => x !== t))}>×</button>
                </span>
              ))}
              <input id={`mf-${name}`} value={tagInput}
                onChange={e => setTagInput(e.target.value)}
                onKeyDown={e => {
                  if (e.key === 'Enter' && tagInput.trim()) {
                    e.preventDefault()
                    const cur = draft[name] || []
                    if (!cur.includes(tagInput.trim())) setField(name, [...cur, tagInput.trim()])
                    setTagInput('')
                  }
                }} placeholder="add tag…" />
            </div>
          ) : (
            <input id={`mf-${name}`} type="text" value={draft[name] ?? ''}
              onChange={e => setField(name, e.target.value || null)} />
          )}
        </div>
      ))}
      {canEdit && (
        <div className="metadata-fields-actions">
          <button type="button" onClick={onSave} disabled={saving || !changed}>
            {saving ? 'Saving…' : 'Save'}
          </button>
          {saved && !error && <span className="field-saved">Saved</span>}
          {error && <span className="field-error">{error}</span>}
        </div>
      )}
    </div>
  )
}

function ReadOnlyValue({ type, value }) {
  if (type === 'tags') {
    return (
      <span>
        {(value || []).map(t => <span key={t} className="tag-chip">{t}</span>)}
      </span>
    )
  }
  return <span>{value ?? '—'}</span>
}
