/**
 * JsonViewer React wrapper — Lane A imperative wrap over src/editors/json-viewer.ts
 *
 * Import from the dedicated subpath to keep CodeMirror out of the main bundle:
 *   import { JsonViewer } from '@countermeasure-platform/web-components/react/editors/json-viewer'
 *
 * API is hybrid controlled/uncontrolled:
 *   - `defaultValue` seeds the editor on mount (uncontrolled)
 *   - `value` + `onChange` enable controlled mode (use with `editable`)
 *
 * In view-only mode (default, `editable` omitted or false), `onChange` is never
 * called because the vanilla class sets the editor read-only.
 */

import * as React from 'react'
import { cn } from '../primitives/utils'
import { JsonViewer as JsonViewerImpl } from '../../editors/json-viewer'
import type { JsonViewerConfig } from '../../editors/types'

export interface JsonViewerProps extends Omit<
  JsonViewerConfig,
  'container' | 'value' | 'onChange'
> {
  /** Uncontrolled initial JSON string. Ignored once `value` is provided. */
  defaultValue?: string
  /** Controlled JSON string. The viewer reflects this value when it changes. */
  value?: string
  /** Fires on every user-initiated change. Only relevant when `editable` is true. */
  onChange?: (value: string) => void
  className?: string
}

function JsonViewer({ defaultValue, value, onChange, className, ...config }: JsonViewerProps) {
  const containerRef = React.useRef<HTMLDivElement>(null)
  const viewerRef = React.useRef<JsonViewerImpl | null>(null)
  const isUpdatingFromProps = React.useRef(false)
  const onChangeRef = React.useRef(onChange)
  onChangeRef.current = onChange

  // Construct once on mount — SSR-safe
  React.useEffect(() => {
    if (typeof document === 'undefined' || !containerRef.current) return
    const initial = value ?? defaultValue ?? ''
    viewerRef.current = new JsonViewerImpl({
      ...config,
      container: containerRef.current,
      value: initial,
      onChange: (next: string) => {
        if (isUpdatingFromProps.current) return
        onChangeRef.current?.(next)
      },
    })
    return () => {
      viewerRef.current?.destroy()
      viewerRef.current = null
    }
  }, [])

  // Sync controlled value into the viewer without re-firing onChange
  React.useEffect(() => {
    const viewer = viewerRef.current
    if (!viewer || value === undefined) return
    if (viewer.getValue() === value) return
    isUpdatingFromProps.current = true
    viewer.setValue(value)
    isUpdatingFromProps.current = false
  }, [value])

  return <div ref={containerRef} data-slot="json-viewer" className={cn('w-full', className)} />
}

JsonViewer.displayName = 'JsonViewer'

export { JsonViewer }
