// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2026 Karim Gabriele Varano
import { useState, useEffect, useMemo } from 'react'
import GeschossManager from './components/FloorManager'
import {
  applyAll, setActiveZeichnungsebene,
  onMessage, notifyReady, applyVisibility,
} from './lib/rhinoBridge'

export function recalcOkff(list) {
  let acc = 0
  return list.map(z => {
    if (z.isGeschoss) {
      const next = { ...z, okff: parseFloat(acc.toFixed(3)) }
      acc += (z.hoehe ?? 3.0)
      return next
    }
    return { ...z, okff: undefined }
  })
}

const INITIAL_ZEICHNUNGSEBENEN = recalcOkff([
  { id: 'eg',  name: 'EG',  isGeschoss: true, hoehe: 3.50, schnitthoehe: 1.00, visible: true },
  { id: '1og', name: '1OG', isGeschoss: true, hoehe: 3.00, schnitthoehe: 1.00, visible: true },
  { id: '2og', name: '2OG', isGeschoss: true, hoehe: 3.00, schnitthoehe: 1.00, visible: true },
])

export default function ZeichnungsebenenApp() {
  const [zeichnungsebenen, setZeichnungsebenen] = useState(INITIAL_ZEICHNUNGSEBENEN)
  const [activeId,         setActiveId]         = useState('eg')
  const [appliedZ,         setAppliedZ]         = useState(INITIAL_ZEICHNUNGSEBENEN)
  const [zMode,            setZMode]            = useState('active')
  const [projectSettings,  setProjectSettings]  = useState(null)

  useEffect(() => {
    onMessage('STATE_SYNC', ({ zeichnungsebenen: z, projectSettings: ps }) => {
      if (ps) setProjectSettings(ps)
      if (z) {
        const r = recalcOkff(z); setZeichnungsebenen(r); setAppliedZ(r)
        const active = r.find(zz => zz.id === activeId) || r[0]
        if (active && !r.find(zz => zz.id === activeId)) {
          setActiveId(active.id)
          setActiveZeichnungsebene(active)
        }
      }
    })
    onMessage('FIRST_RUN', () => {
      // Backend hat keine doc.Strings → wir senden den Default an Backend
      // (nur unsere Slice; ebenen fuellt Backend aus doc.Strings oder leerer
      // Liste vom anderen Panel beim FIRST_RUN dort).
      applyAll(INITIAL_ZEICHNUNGSEBENEN, [])
      setAppliedZ(INITIAL_ZEICHNUNGSEBENEN)
      const active = INITIAL_ZEICHNUNGSEBENEN.find(zz => zz.id === activeId) || INITIAL_ZEICHNUNGSEBENEN[0]
      if (active) setActiveZeichnungsebene(active)
    })
    notifyReady()
    const blockContext = (ev) => ev.preventDefault()
    document.addEventListener('contextmenu', blockContext)
    return () => document.removeEventListener('contextmenu', blockContext)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  // Sichtbarkeit live anwenden bei Mode-/Visibility-/Lock-Aenderungen
  const visibilityKey = useMemo(() => (
    activeId + '|' + zMode + '|' +
    zeichnungsebenen.map(z => `${z.id}:${z.visible !== false ? 1 : 0}:${z.locked ? 1 : 0}`).join(',')
  ), [activeId, zMode, zeichnungsebenen])

  useEffect(() => {
    const activeZ = zeichnungsebenen.find(z => z.id === activeId)
    if (activeZ) {
      // Backend merged mit doc.Strings: aktiveCode + eMode kommen von dort
      applyVisibility(activeZ, zeichnungsebenen, null, [], zMode, null)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [visibilityKey])

  // Auto-Apply bei strukturellen Aenderungen (add/remove/rename, hoehe,
  // schnitthoehe, hasClipping). Nur ZEICHNUNGSEBENEN-Slice senden — Backend
  // mergt mit doc.Strings.
  const zSig = (z) => [
    z.id, z.name, z.isGeschoss ? 1 : 0,
    z.hoehe ?? '', z.schnitthoehe ?? '',
    z.hasClipping ? 1 : 0,
  ].join(':')
  const structureKey = useMemo(() => (
    zeichnungsebenen.map(zSig).join(',')
  ), [zeichnungsebenen])
  const appliedStructureKey = useMemo(() => (
    appliedZ.map(zSig).join(',')
  ), [appliedZ])

  useEffect(() => {
    if (structureKey === appliedStructureKey) return
    console.log('[ZEICHNUNGSEBENEN-UI] structureKey diff → schedule applyAll in 200ms', {
      zCount: zeichnungsebenen.length, appliedCount: appliedZ.length,
    })
    const t = setTimeout(() => {
      console.log('[ZEICHNUNGSEBENEN-UI] applyAll firing now', { zCount: zeichnungsebenen.length })
      applyAll(zeichnungsebenen, [])
      setAppliedZ(zeichnungsebenen)
    }, 200)
    return () => clearTimeout(t)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [structureKey, appliedStructureKey])

  const handleActiveChange = (id) => {
    setActiveId(id)
    const z = zeichnungsebenen.find(x => x.id === id)
    if (z) setActiveZeichnungsebene(z)
  }

  return (
    <div style={{
      display: 'flex', flexDirection: 'column',
      height: '100vh', overflow: 'hidden',
      background: 'var(--bg-base)',
      position: 'relative',
    }}>
      <div style={{ flex: 1, overflowY: 'auto' }}>
        <GeschossManager
          zeichnungsebenen={zeichnungsebenen}
          activeId={activeId}
          onActiveChange={handleActiveChange}
          onChange={(updated) => setZeichnungsebenen(recalcOkff(updated))}
          recalcOkff={recalcOkff}
          mode={zMode}
          onModeChange={setZMode}
          projectSettings={projectSettings}
        />
      </div>
    </div>
  )
}
