import { useState, useEffect, useRef } from 'react'
import Icon from './components/Icon'
import {
  onMessage, notifyReady,
  requestMassstab, setMassstab,
  zoomExtents, zoomSelection, setShowLineweights,
  setMassstabDpi, detectMassstabDpi,
  setView, setDisplayMode,
  toggleOverrides, setOverridesPreset, openOverridesPanel,
  pickLayerCombination, saveLayerCombination,
  deleteLayerCombination, openLayerCombinationsDialog,
  openDossierSettings,
} from './lib/rhinoBridge'

const PRESETS = [
  { value: 1, label: '1:1' }, { value: 5, label: '1:5' },
  { value: 10, label: '1:10' }, { value: 20, label: '1:20' },
  { value: 25, label: '1:25' }, { value: 50, label: '1:50' },
  { value: 100, label: '1:100' }, { value: 200, label: '1:200' },
  { value: 500, label: '1:500' }, { value: 1000, label: '1:1000' },
]

const VIEWS = [
  { value: 'Top',         icon: 'north',          label: 'Top' },
  { value: 'Front',       icon: 'view_in_ar',     label: 'Front' },
  { value: 'Right',       icon: 'east',           label: 'Right' },
  { value: 'Perspective', icon: 'view_quilt',     label: 'Persp' },
]

function fmtScale(s) {
  if (s == null) return '—'
  if (s >= 1) return '1:' + (s >= 10 ? s.toFixed(0) : s.toFixed(1))
  return (1 / s).toFixed(2) + ':1'
}

function snapToPreset(s, tol = 0.03) {
  if (s == null) return null
  for (const p of PRESETS) {
    if (Math.abs(s - p.value) / p.value <= tol) return p.value
  }
  return null
}

function parseScale(input) {
  if (!input) return null
  const s = String(input).trim()
  for (const sep of [':', '=', '/']) {
    if (s.includes(sep)) {
      const [a, b] = s.split(sep, 2)
      const pa = parseFloat(a), pb = parseFloat(b)
      if (pa > 0 && pb > 0) return pb / pa
      return null
    }
  }
  const n = parseFloat(s)
  return n > 0 ? n : null
}

// ---------------------------------------------------------------------------
// Material-UI-Style: alle Pills auf einheitliche Hoehe (PILL_H)
// nutzt globale Klassen aus index.css fuer Look (border-radius, colors)

const PILL_H = 20  // Einheits-Hoehe fuer alle Bar-Elemente

const sep = {
  width: 1, height: 18,
  background: 'var(--border)', flexShrink: 0,
  margin: '0 2px',
}
const groupLabel = {
  fontSize: 9, color: 'var(--text-muted)', textTransform: 'uppercase',
  letterSpacing: '0.08em', fontWeight: 600,
  alignSelf: 'center', whiteSpace: 'nowrap',
  padding: '0 4px',
}
const pillSelect = {
  height: PILL_H, lineHeight: PILL_H + 'px',
  padding: '0 20px 0 10px', boxSizing: 'border-box',
  fontSize: 10,
}
const pillInput = {
  height: PILL_H, lineHeight: PILL_H + 'px',
  padding: '0 8px', boxSizing: 'border-box',
  borderRadius: 999,
  fontSize: 10,
}
const pillChip = {
  height: PILL_H, lineHeight: PILL_H + 'px',
  padding: '0 8px', boxSizing: 'border-box',
  display: 'inline-flex', alignItems: 'center',
  fontSize: 9,
}
const pillIconBtn = {
  width: PILL_H, height: PILL_H,
  borderRadius: '50%', boxSizing: 'border-box',
}

// Tonal button helper (filled when active, outlined when not)
function ToolButton({ active, onClick, icon, label, title, disabled }) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      className={active ? 'btn-contained' : 'btn-outlined'}
      style={{ height: PILL_H, padding: '0 8px', boxSizing: 'border-box',
               fontSize: 9,
               opacity: disabled ? 0.4 : 1,
               cursor: disabled ? 'not-allowed' : 'pointer' }}
      title={title}
    >
      {icon && <Icon name={icon} size={12} />}
      {label && <span style={{ fontSize: 9 }}>{label}</span>}
    </button>
  )
}

// ---------------------------------------------------------------------------

export default function OberleisteApp() {
  const [state, setState] = useState({
    viewName: null, parallel: false, scale: null,
    pixelWidth: null, pixelHeight: null, unitSystem: '?',
    dpi: 96, dpiSource: 'default',
    showLineweights: false,
    viewMode: null, displayMode: null, displayModes: [],
    ortho: false, gridSnap: false, osnap: false,
    overridesEnabled: false, overridesCount: 0,
    cmdPrompt: '', cmdOptions: [],
    overridesActivePreset: null, overridesPresets: [],
    layerCombinations: [], layerCombinationActive: null,
  })
  const [appliedScale, setAppliedScale] = useState(null)
  const appliedScaleRef = useRef(null)
  const [draft, setDraft] = useState('')
  const [customMode, setCustomMode] = useState(false)  // Dropdown -> Custom-Input switch
  const customInputRef = useRef(null)

  useEffect(() => {
    onMessage('STATE', (s) => {
      setState((prev) => ({ ...prev, ...s }))
      // Dropdown spiegelt EXAKT den Backend-appliedScale fuer den aktuellen
      // Viewport. Kein Live-Skala-Fallback — das Dropdown ist statisch und
      // pro Viewport gebunden. Backend gibt null zurueck wenn der aktive
      // Viewport noch keinen gesetzten Massstab hat → Dropdown zeigt "1:?".
      const next = (typeof s?.appliedScale === 'number' && s.appliedScale > 0)
        ? s.appliedScale
        : null
      if (next !== appliedScaleRef.current) {
        setAppliedScale(next)
        appliedScaleRef.current = next
      }
    })
    notifyReady()
    setTimeout(() => requestMassstab(), 50)
  }, [])

  const isPerspective = state.parallel === false
  const scaleVal = state.scale
  const dropdownValue = appliedScale != null ? String(appliedScale) : '__none__'

  const applyDropdown = (val) => {
    if (val === '__none__') return
    if (val === '__custom__') {
      setDraft(appliedScale ? `1:${appliedScale}` : '')
      setCustomMode(true)
      // Nach dem Render: Focus + Selektion fuer schnelles Eintippen.
      setTimeout(() => {
        customInputRef.current?.focus()
        customInputRef.current?.select()
      }, 0)
      return
    }
    const r = parseFloat(val)
    if (r > 0) { setAppliedScale(r); appliedScaleRef.current = r; setMassstab(r) }
  }
  const applyDraft = () => {
    const r = parseScale(draft)
    if (r != null) {
      setAppliedScale(r); appliedScaleRef.current = r; setMassstab(r)
    }
    setDraft('')
    setCustomMode(false)
  }
  const cancelDraft = () => { setDraft(''); setCustomMode(false) }
  const apply100 = () => {
    if (appliedScale && appliedScale > 0) setMassstab(appliedScale)
  }

  // Aktuelles View-Match (manche User haben "Top" / "Right" als view name)
  const matchView = (v) => {
    if (!state.viewName) return false
    return state.viewName === v || state.viewName.toLowerCase() === v.toLowerCase()
  }

  // (Command-Bar wurde entfernt — Rhinos eigene Command-Line wird benutzt.)

  return (
    <div style={{
      width: '100%', height: '100%',
      display: 'flex', flexDirection: 'column',
      fontFamily: 'var(--font)', color: 'var(--text-primary)',
      background: 'var(--bg-panel)',
      borderBottom: '1px solid var(--border)',
      boxSizing: 'border-box',
      overflow: 'hidden',
    }}>
    {/* === Toolbar (View, Display, Massstab, Snap, Overrides) === */}
    <div style={{
      display: 'flex', alignItems: 'center', gap: 8,
      padding: '6px 12px',
      overflowX: 'auto', overflowY: 'hidden',
      flexShrink: 0,
    }}>
      <span
        style={{
          fontSize: 11, fontWeight: 600, letterSpacing: '0.08em',
          color: 'var(--text-muted)',
          fontFamily: 'DM Mono, monospace',
          flexShrink: 0, userSelect: 'none',
        }}
        title={`Dossier ${__APP_VERSION__} — Teil von OpenStudio`}
      >
        DOSSIER <span style={{ opacity: 0.55 }}>{__APP_VERSION__}</span>
      </span>
      <button
        onClick={() => openDossierSettings()}
        title="Dossier-Einstellungen"
        style={{
          background: 'transparent', border: 'none', padding: '2px 4px',
          cursor: 'pointer', color: 'var(--text-muted)',
          display: 'flex', alignItems: 'center', flexShrink: 0,
        }}
        onMouseEnter={(e) => e.currentTarget.style.color = 'var(--text-primary)'}
        onMouseLeave={(e) => e.currentTarget.style.color = 'var(--text-muted)'}
      >
        <Icon name="settings" size={14} />
      </button>
      <div style={sep} />
      {/* ====== GRUPPE: VIEW ====== */}
      <span style={groupLabel}>View</span>
      {VIEWS.map(v => (
        <ToolButton
          key={v.value}
          onClick={() => setView(v.value)}
          active={matchView(v.value)}
          icon={v.icon}
          label={v.label}
          title={`Ansicht ${v.label}`}
        />
      ))}

      <div style={sep} />

      {/* ====== GRUPPE: DISPLAY-MODE ====== */}
      <span style={groupLabel}>Display</span>
      <select
        value={state.displayMode || ''}
        onChange={(e) => setDisplayMode(e.target.value)}
        style={pillSelect}
        title="Display-Mode (Wireframe / Shaded / Rendered / etc.)"
      >
        {!state.displayMode && <option value="">—</option>}
        {(state.displayModes || []).map(dm => (
          <option key={dm.id} value={dm.name}>{dm.name}</option>
        ))}
      </select>

      <div style={sep} />

      {/* ====== GRUPPE: MASSSTAB ====== */}
      <span style={groupLabel}>Massstab</span>
      <span
        className={isPerspective ? 'chip' : 'chip chip-accent'}
        style={{
          ...pillChip,
          minWidth: 56, justifyContent: 'center',
          fontFamily: 'DM Mono, monospace', fontSize: 11, fontWeight: 600,
        }}
        title="Live-Zoom"
      >
        {/* Live-Zoom des Viewports — immer sichtbar bei Parallelprojektion,
            unabhaengig davon ob ein Massstab im Dropdown gepinnt ist oder
            nicht. Nur in Perspective ist die Anzeige nicht sinnvoll. */}
        {isPerspective ? '—' : fmtScale(scaleVal)}
      </span>
      {customMode ? (
        <input
          ref={customInputRef}
          disabled={isPerspective}
          type="text" placeholder="1:N"
          value={draft}
          onChange={(e) => setDraft(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === 'Enter') applyDraft()
            else if (e.key === 'Escape') cancelDraft()
          }}
          onBlur={applyDraft}
          style={{ ...pillInput, width: 92 }}
          title="Massstab eingeben (Enter = uebernehmen, Esc = abbrechen)"
        />
      ) : (
        <select
          disabled={isPerspective}
          value={dropdownValue}
          onChange={(e) => applyDropdown(e.target.value)}
          style={{ ...pillSelect, width: 92 }}
        >
          <option value="__none__">—</option>
          {PRESETS.map(p => (
            <option key={p.value} value={String(p.value)}>{p.label}</option>
          ))}
          {appliedScale != null && !PRESETS.some(p => p.value === appliedScale) && (
            <option value={String(appliedScale)}>1:{appliedScale}</option>
          )}
          <option value="__custom__">Eigener…</option>
        </select>
      )}
      <ToolButton
        onClick={apply100}
        disabled={isPerspective || !appliedScale}
        label="100%"
        title={appliedScale ? `Zoom auf eingestellten Massstab snappen (1:${appliedScale >= 10 ? Math.round(appliedScale) : appliedScale})` : 'Erst einen Massstab wählen'}
      />
      <button className="btn-icon" onClick={zoomExtents}
              style={pillIconBtn}
              title="Auf gesamten Inhalt zoomen">
        <Icon name="fit_screen" size={14} />
      </button>
      <button className="btn-icon" onClick={zoomSelection}
              style={pillIconBtn}
              title="Auf Selektion zoomen">
        <Icon name="center_focus_strong" size={14} />
      </button>
      <ToolButton
        onClick={() => setShowLineweights(!state.showLineweights)}
        active={state.showLineweights}
        label={state.showLineweights ? 'Print' : 'Edit'}
        title={state.showLineweights ? 'Print-View aktiv — klick zum Ausschalten' : 'Strichstärken anzeigen (Print-View)'}
        icon={state.showLineweights ? 'print' : 'edit'}
      />

      <div style={sep} />

      {/* Snap-Toggles (Ortho/Grid/OSnap) sind in Rhinos eigener Footer-Bar
          schon vorhanden — hier rausgenommen um Doppelung zu vermeiden. */}

      {/* ====== GRUPPE: OVERRIDES ====== */}
      <span style={groupLabel}>Overrides</span>
      <ToolButton
        onClick={() => toggleOverrides(!state.overridesEnabled)}
        active={state.overridesEnabled}
        icon="auto_fix_high"
        label={state.overridesEnabled ? 'AN' : 'AUS'}
        title={state.overridesEnabled
          ? `Grafische Overrides aktiv — klick zum Ausschalten`
          : `Grafische Overrides ausgeschaltet`}
      />
      {/* Preset-Dropdown: aktive Kombination waehlen. "—" = keine Kombination
          (Doc-Rules sind frei editiert oder leer). "Konfigurieren…" oeffnet
          den grossen Regel-Editor (OVERRIDES-Panel). */}
      <select
        value={state.overridesActivePreset || '__none__'}
        onChange={(e) => {
          const v = e.target.value
          if (v === '__configure__') { openOverridesPanel(); return }
          setOverridesPreset(v === '__none__' ? null : v)
        }}
        style={{ ...pillSelect, width: 140 }}
        title={state.overridesActivePreset
          ? `Aktives Preset: ${state.overridesActivePreset} (${state.overridesCount} Regeln)`
          : `Kein Preset aktiv (${state.overridesCount} Regeln, frei editiert)`}
      >
        <option value="__none__">{state.overridesCount > 0 ? `— (${state.overridesCount} Regeln)` : '—'}</option>
        {(state.overridesPresets || []).map(name => (
          <option key={name} value={name}>{name}</option>
        ))}
        <option disabled>──────────</option>
        <option value="__configure__">Konfigurieren…</option>
      </select>
      <ToolButton
        onClick={openOverridesPanel}
        icon="settings"
        title="Overrides-Regel-Editor öffnen"
      />

      <div style={sep} />

      {/* ====== GRUPPE: EBENENKOMBINATION ====== */}
      <span style={groupLabel}>Kombi</span>
      <select
        value={state.layerCombinationActive || '__none__'}
        onChange={(e) => {
          const v = e.target.value
          if (v === '__configure__') { openLayerCombinationsDialog(); return }
          if (v === '__delete__') {
            if (state.layerCombinationActive &&
                window.confirm(`Kombination "${state.layerCombinationActive}" löschen?`))
              deleteLayerCombination(state.layerCombinationActive)
            return
          }
          pickLayerCombination(v === '__none__' ? null : v)
        }}
        style={{ ...pillSelect, width: 140 }}
        title={state.layerCombinationActive
          ? `Aktive Kombi: ${state.layerCombinationActive}`
          : 'Keine Kombination — manuelle Sichtbarkeit'}
      >
        <option value="__none__">— Eigene —</option>
        {(state.layerCombinations || []).map(name => (
          <option key={name} value={name}>{name}</option>
        ))}
        {state.layerCombinationActive && (
          <>
            <option disabled>──────────</option>
            <option value="__delete__">🗑 Aktuelle löschen</option>
          </>
        )}
        <option disabled>──────────</option>
        <option value="__configure__">Bearbeiten…</option>
      </select>
      <ToolButton
        onClick={() => {
          const suggested = state.layerCombinationActive
            || `Kombi ${(state.layerCombinations || []).length + 1}`
          const name = (window.prompt('Name für Ebenenkombination:', suggested) || '').trim()
          if (!name) return
          if ((state.layerCombinations || []).includes(name) &&
              !window.confirm(`"${name}" überschreiben?`)) return
          saveLayerCombination(name)
        }}
        icon="add"
        title="Aktuelle Sichtbarkeit als neue Kombination speichern"
      />
      <ToolButton
        onClick={openLayerCombinationsDialog}
        icon="edit"
        title="Ebenenkombinationen bearbeiten"
      />

      {/* Spacer am rechten Rand */}
      <div style={{ flex: 1 }} />
    </div>
    </div>
  )
}
