// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2026 Karim Gabriele Varano
import { useState, useEffect, useRef } from 'react'
import Icon from './components/Icon'
import { BarToggle, BAR_H } from './components/BarControls'
import { onMessage, notifyReady } from './lib/rhinoBridge'

function send(type, payload = {}) {
  if (!window.RHINO_MODE) { console.log('[OSM] →', type, payload); return }
  document.title = 'RHINOMSG::' + JSON.stringify({ type, payload })
}

const pillInput = {
  height: BAR_H,
  background: 'var(--bg-input)',
  border: '1px solid var(--border)',
  borderRadius: 999,
  color: 'var(--text-primary)',
  fontSize: 11, fontFamily: 'var(--font)',
  padding: '0 10px',
  outline: 'none',
  boxSizing: 'border-box',
}

function Field({ label, hint, children }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 4, padding: '6px 0' }}>
      {label && <span className="label-xs">{label}</span>}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>{children}</div>
      {hint && (
        <span style={{ fontSize: 9, color: 'var(--text-muted)', lineHeight: 1.4 }}>{hint}</span>
      )}
    </div>
  )
}

function SectionLabel({ children }) {
  return (
    <div style={{
      fontSize: 9, color: 'var(--text-muted)', fontWeight: 600,
      letterSpacing: 0.5, textTransform: 'uppercase',
      padding: '10px 0 4px',
      borderTop: '1px solid var(--border-light)',
      marginTop: 8,
    }}>{children}</div>
  )
}

function Radio({ value, options, onChange }) {
  return (
    <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
      {options.map(o => (
        <BarToggle key={o.value} label={o.label}
          active={value === o.value}
          onClick={() => onChange(o.value)} />
      ))}
    </div>
  )
}

// OSM-Kategorien — Keys matchen das Backend (osm.py CATEGORIES).
const CATEGORIES = [
  { key: 'streets',   label: 'Strassen',           icon: 'route',
    hint: 'Autobahn/Hauptstrasse/Quartierstrasse → Polylinien' },
  { key: 'buildings', label: 'Gebäudeumrisse',     icon: 'apartment',
    hint: 'building=* Umrisse als geschlossene Polylinien' },
  { key: 'water',     label: 'Wasser (Flächen)',   icon: 'water',
    hint: 'natural=water (Seen, Teiche)' },
  { key: 'waterways', label: 'Wasserläufe',        icon: 'waves',
    hint: 'waterway=river/stream/canal' },
  { key: 'parks',     label: 'Parks',              icon: 'park',
    hint: 'leisure=park/garden' },
  { key: 'forest',    label: 'Wald & Grün',        icon: 'forest',
    hint: 'landuse=forest/grass/meadow' },
  { key: 'footpaths', label: 'Fuss-/Radwege',      icon: 'directions_walk',
    hint: 'highway=footway/path/track/cycleway' },
]

export default function OsmApp() {
  // Standort
  const [searchText, setSearchText] = useState('')
  const [center,     setCenter]     = useState(null)
  const [searching,  setSearching]  = useState(false)
  // Optionen
  const [radius,     setRadius]     = useState(200)
  const [selected,   setSelected]   = useState({
    streets: true, buildings: true, waterways: true,
    parks: true, forest: true,
    water: false, footpaths: false,
  })
  const [shift,      setShift]      = useState(true)
  const [autoZoom,   setAutoZoom]   = useState(true)
  const [replaceExisting, setReplaceExisting] = useState(true)
  // Live-Log
  const [logs,       setLogs]       = useState([])
  const [running,    setRunning]    = useState(false)
  const [done,       setDone]       = useState(false)
  const logRef = useRef(null)

  useEffect(() => {
    onMessage('GEOCODE_RESULT', ({ result }) => {
      setSearching(false)
      if (result && result.e != null && result.n != null) {
        setCenter({ e: result.e, n: result.n, label: result.label || searchText })
      } else {
        setCenter(null)
        addLog('Keine Adresse gefunden')
      }
    })
    onMessage('OSM_LOG', ({ msg }) => addLog(msg))
    onMessage('IMPORT_DONE', ({ count }) => {
      setRunning(false); setDone(true)
      addLog(`✓ Fertig — ${count} OSM-Objekt(e) importiert`)
    })
    notifyReady()
    const blockContext = (ev) => ev.preventDefault()
    document.addEventListener('contextmenu', blockContext)
    return () => document.removeEventListener('contextmenu', blockContext)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  useEffect(() => {
    if (logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight
  }, [logs])

  const addLog = (m) => setLogs(l => [...l, m])

  const handleSearch = () => {
    const t = searchText.trim()
    if (!t) return
    setSearching(true); setCenter(null)
    addLog(`Suche '${t}'...`)
    send('GEOCODE', { text: t })
  }

  const handleManualCoords = (eRaw, nRaw) => {
    const e = parseFloat(eRaw), n = parseFloat(nRaw)
    if (e > 2000000 && n > 1000000) {
      setCenter({ e, n, label: `LV95 manuell` })
    } else {
      setCenter(null)
    }
  }

  const handleImport = () => {
    if (!center) { addLog('Bitte zuerst einen Standort wählen'); return }
    const cats = Object.entries(selected).filter(([, v]) => v).map(([k]) => k)
    if (cats.length === 0) { addLog('Mindestens eine Kategorie auswählen'); return }
    setLogs([]); setRunning(true); setDone(false)
    send('RUN_OSM_IMPORT', {
      centerE: center.e, centerN: center.n,
      radius: Number(radius),
      categories: cats,
      shiftToOrigin: shift,
      autoZoom,
      replaceExisting,
    })
  }

  const toggleCat = (key) => {
    setSelected(s => ({ ...s, [key]: !s[key] }))
  }

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: 'var(--bg-dialog)',
      display: 'flex', flexDirection: 'column',
      fontFamily: 'var(--font)', color: 'var(--text-primary)',
      overflow: 'hidden',
    }}>
      <div style={{ flex: 1, overflowY: 'auto', padding: '10px 16px' }}>

        <SectionLabel>Standort</SectionLabel>

        <Field label="ADRESSE / ORT" hint='z.B. "Bahnhofstrasse 1, Zürich"'>
          <input
            value={searchText}
            onChange={(e) => setSearchText(e.target.value)}
            onKeyDown={(e) => { if (e.key === 'Enter') handleSearch() }}
            placeholder="Adresse oder Ortsname"
            style={{ ...pillInput, flex: 1 }}
          />
          <BarToggle label={searching ? '…' : 'Suchen'}
            onClick={handleSearch}
            disabled={searching || !searchText.trim()} />
        </Field>

        <Field label="ODER LV95-KOORDS (E / N)"
                hint="Falls aus Swisstopo-Import übernommen">
          <input placeholder="E"
            onChange={(e) => handleManualCoords(e.target.value, center?.n || '')}
            style={{ ...pillInput, width: 110, fontFamily: 'DM Mono, monospace' }} />
          <span style={{ color: 'var(--text-muted)' }}>/</span>
          <input placeholder="N"
            onChange={(e) => handleManualCoords(center?.e || '', e.target.value)}
            style={{ ...pillInput, width: 110, fontFamily: 'DM Mono, monospace' }} />
        </Field>

        {center && (
          <div style={{
            display: 'flex', alignItems: 'center', gap: 8,
            padding: '8px 12px',
            background: 'var(--accent-dim)',
            border: '1px solid var(--accent-border)',
            borderRadius: 999,
            marginTop: 4,
          }}>
            <Icon name="location_on" size={14} style={{ color: 'var(--accent)' }} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 11, fontWeight: 500, overflow: 'hidden',
                            textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{center.label}</div>
              <div style={{ fontSize: 9, fontFamily: 'DM Mono, monospace',
                            color: 'var(--text-muted)' }}>
                E {Math.round(center.e)} · N {Math.round(center.n)}
              </div>
            </div>
          </div>
        )}

        <SectionLabel>Bereich</SectionLabel>
        <Field label="RADIUS">
          <Radio value={radius}
            options={[
              { value: 100, label: '100 m' },
              { value: 200, label: '200 m' },
              { value: 500, label: '500 m' },
              { value: 1000, label: '1 km' },
            ]}
            onChange={setRadius} />
        </Field>

        <SectionLabel>Kategorien</SectionLabel>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
          {CATEGORIES.map(cat => (
            <label key={cat.key}
              style={{ display: 'flex', alignItems: 'center', gap: 8,
                       fontSize: 11, cursor: 'pointer', padding: '3px 0' }}
              title={cat.hint}>
              <input type="checkbox" checked={!!selected[cat.key]}
                onChange={() => toggleCat(cat.key)} />
              <Icon name={cat.icon} size={13} />
              <span>{cat.label}</span>
            </label>
          ))}
        </div>

        <SectionLabel>Positionierung</SectionLabel>
        <Field label="ORIGIN"
                hint="LV95-Koords sind im Mio-Bereich. Auf 0/0/0 verschiebt zum aktiven Standort.">
          <Radio value={shift ? 'origin' : 'lv95'}
            options={[
              { value: 'origin', label: 'Auf Welt-Origin verschieben' },
              { value: 'lv95',   label: 'Original LV95 lassen' },
            ]}
            onChange={(v) => setShift(v === 'origin')} />
        </Field>

        <Field label="">
          <label style={{ display: 'flex', alignItems: 'center', gap: 6,
                           fontSize: 11, cursor: 'pointer' }}>
            <input type="checkbox" checked={autoZoom}
              onChange={(e) => setAutoZoom(e.target.checked)} />
            Auto-Zoom auf importierte Objekte
          </label>
        </Field>

        <Field label=""
                hint="Bestehende OSM-Objekte (Tag dossier_osm_kind) werden vorher gelöscht.">
          <label style={{ display: 'flex', alignItems: 'center', gap: 6,
                           fontSize: 11, cursor: 'pointer' }}>
            <input type="checkbox" checked={replaceExisting}
              onChange={(e) => setReplaceExisting(e.target.checked)} />
            Bestehende OSM-Objekte vorher löschen
          </label>
        </Field>

        <SectionLabel>Status</SectionLabel>
        <div ref={logRef} style={{
          height: 140, overflowY: 'auto',
          padding: 8, fontSize: 10,
          fontFamily: 'DM Mono, monospace',
          background: 'var(--bg-base)',
          border: '1px solid var(--border-light)',
          borderRadius: 'var(--r-lg)',
          color: 'var(--text-secondary)',
          whiteSpace: 'pre-wrap',
        }}>
          {logs.length === 0
            ? <span style={{ color: 'var(--text-muted)' }}>Bereit</span>
            : logs.map((l, i) => <div key={i}>{l}</div>)}
          {running && <div style={{ color: 'var(--accent)' }}>Läuft…</div>}
        </div>
      </div>

      <div style={{
        display: 'flex', alignItems: 'center', gap: 6,
        padding: '8px 12px',
        borderTop: '1px solid var(--border)',
        background: 'var(--bg-section)',
      }}>
        <div style={{ fontSize: 9, color: 'var(--text-muted)', flex: 1 }}>
          Quelle: Overpass-API · © OpenStreetMap-Mitwirkende (ODbL)
        </div>
        <BarToggle label="Abbrechen" onClick={() => send('CANCEL')} />
        <BarToggle icon="download"
          label={running ? 'Lädt…' : 'Importieren'}
          active
          disabled={running || !center}
          onClick={handleImport} />
      </div>
    </div>
  )
}
