/* App-shell: authenticatie, databootstrap, routing en tweaks */

const { useState, useEffect } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "kleurrijk",
  "bg": "papier",
  "density": "standard"
}/*EDITMODE-END*/;

const BG_SWATCHES = {
  creme:  '#F4ECE3',
  papier: '#F6F4EE',
  zand:   '#F2EBD9',
  steen:  '#EDF0F4',
  mint:   '#E6F1EB',
  inkt:   '#1D2330',
};
const BG_LABELS = {
  creme: 'Crème-roze',
  papier: 'Papier',
  zand: 'Zand',
  steen: 'Steen',
  mint: 'Mint',
  inkt: 'Inkt',
};

// pas de standaardthema-attributen direct toe (ook voor inlog- en laadscherm)
document.documentElement.setAttribute('data-theme', TWEAK_DEFAULTS.theme);
document.documentElement.setAttribute('data-density', TWEAK_DEFAULTS.density);
document.documentElement.setAttribute('data-bg', TWEAK_DEFAULTS.bg);

function parseRoute(hash) {
  const h = (hash || '').replace(/^#\/?/, '') || 'dashboard';
  const [section, id] = h.split('/');
  return { section, id };
}

function useRoute() {
  const [hash, setHash] = useState(window.location.hash);
  useEffect(() => {
    const onChange = () => setHash(window.location.hash);
    window.addEventListener('hashchange', onChange);
    return () => window.removeEventListener('hashchange', onChange);
  }, []);
  const route = parseRoute(hash);
  const navigate = (path) => { window.location.hash = '#/' + path; window.scrollTo(0, 0); };
  return { route, navigate };
}

/* ------------------------------------------------------------------ */
/*  Laadscherm                                                         */
/* ------------------------------------------------------------------ */
function Splash({ text }) {
  return (
    <div style={{ minHeight: '100vh', display: 'grid', placeItems: 'center', background: 'var(--bg)' }}>
      <div style={{ textAlign: 'center' }}>
        <div style={{ fontSize: 22, fontWeight: 800, letterSpacing: '-0.01em' }}>
          SCHOENERWEG<span style={{ color: 'var(--accent)' }}>.</span>
        </div>
        <div className="muted" style={{ marginTop: 10, fontSize: 13 }}>{text || 'Laden…'}</div>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  Hoofdapplicatie (na inloggen)                                      */
/* ------------------------------------------------------------------ */
/* ============================================================
   ZOEKEN
   Eén veld voor alles wat in het systeem staat: huurders,
   facturen, contracten, onderhoudsmeldingen en documenten.
   ⌘K / Ctrl-K zet de cursor erin, pijltjes en Enter kiezen.
   ============================================================ */
function Zoeken({ navigate }) {
  const { Icons } = window;
  const [q, setQ] = React.useState('');
  const [open, setOpen] = React.useState(false);
  const [actief, setActief] = React.useState(0);
  const veld = React.useRef(null);
  const doos = React.useRef(null);

  const D = window.SW_DATA;
  const { fmtEUR, fmtDate } = D;

  React.useEffect(() => {
    const opToets = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
        e.preventDefault();
        veld.current && veld.current.focus();
      }
    };
    const opKlik = (e) => {
      if (doos.current && !doos.current.contains(e.target)) setOpen(false);
    };
    window.addEventListener('keydown', opToets);
    window.addEventListener('mousedown', opKlik);
    return () => {
      window.removeEventListener('keydown', opToets);
      window.removeEventListener('mousedown', opKlik);
    };
  }, []);

  const term = q.trim().toLowerCase();
  const treffers = React.useMemo(() => {
    if (term.length < 2) return [];
    const bevat = (...velden) =>
      velden.filter(Boolean).some(v => String(v).toLowerCase().includes(term));
    const uit = [];

    for (const t of D.TENANTS || []) {
      if (bevat(t.name, t.contact, t.email, t.invoiceEmail, t.unit, t.unitAddress)) {
        uit.push({
          soort: 'Huurder', titel: t.name,
          detail: `Unit ${t.unit} · ${fmtEUR(t.rentNet)} per maand`,
          naar: 'tenants/' + t.id,
        });
      }
    }
    for (const c of D.TENANTS || []) {
      if (bevat('contract', c.name) && term.includes('contract')) {
        uit.push({
          soort: 'Contract', titel: `Contract ${c.name}`,
          detail: `Unit ${c.unit} · ${c.endDate ? 'tot ' + fmtDate(c.endDate) : 'doorlopend'}`,
          naar: 'contracts/' + c.id,
        });
      }
    }
    for (const i of D.INVOICES || []) {
      if (bevat(i.number, i.tenantName, i.periodLabel)) {
        uit.push({
          soort: 'Factuur', titel: i.number,
          detail: `${i.tenantName} · ${i.periodLabel} · ${fmtEUR(i.total)} · ` +
            (i.paid ? 'betaald' : i.sent ? 'open' : 'concept'),
          naar: 'invoices/' + i.id,
        });
      }
    }
    for (const m of D.MAINTENANCE || []) {
      if (bevat(m.title, m.description, m.unit, m.contractor)) {
        uit.push({
          soort: 'Onderhoud', titel: m.title,
          detail: `${m.unit ? 'Unit ' + m.unit + ' · ' : ''}${m.status}`,
          naar: 'maintenance/' + m.id,
        });
      }
    }
    for (const doc of D.DOCUMENTS || []) {
      if (bevat(doc.name, doc.category)) {
        uit.push({
          soort: 'Document', titel: doc.name,
          detail: doc.category, naar: 'documents',
        });
      }
    }
    return uit.slice(0, 12);
  }, [term, D]);

  React.useEffect(() => { setActief(0); }, [term]);

  const kies = (t) => {
    if (!t) return;
    setOpen(false);
    setQ('');
    veld.current && veld.current.blur();
    navigate(t.naar);
  };

  const opVeldToets = (e) => {
    if (e.key === 'Escape') { setOpen(false); veld.current.blur(); return; }
    if (!treffers.length) return;
    if (e.key === 'ArrowDown') { e.preventDefault(); setActief(i => (i + 1) % treffers.length); }
    else if (e.key === 'ArrowUp') { e.preventDefault(); setActief(i => (i - 1 + treffers.length) % treffers.length); }
    else if (e.key === 'Enter') { e.preventDefault(); kies(treffers[actief]); }
  };

  return (
    <div className="zoekdoos" ref={doos}>
      <div className="input-with-icon">
        <Icons.Search />
        <input ref={veld} className="input search" value={q}
               placeholder="Zoek huurder, factuur, melding…"
               onChange={e => { setQ(e.target.value); setOpen(true); }}
               onFocus={() => setOpen(true)}
               onKeyDown={opVeldToets} />
      </div>
      {open && term.length >= 2 && (
        <div className="zoekresultaten">
          {treffers.length === 0
            ? <div className="zoek-leeg">Niets gevonden voor “{q}”.</div>
            : treffers.map((t, i) => (
                <button key={t.soort + t.naar + i}
                        className={'zoek-treffer' + (i === actief ? ' actief' : '')}
                        onMouseEnter={() => setActief(i)}
                        onClick={() => kies(t)}>
                  <span className="zoek-soort">{t.soort}</span>
                  <span className="zoek-titel">{t.titel}</span>
                  <span className="zoek-detail">{t.detail}</span>
                </button>
              ))}
        </div>
      )}
    </div>
  );
}

function App({ onLogout }) {
  const [tweaks, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const [mobileOpen, setMobileOpen] = useState(false);
  const [, setVersion] = useState(0);
  const { route, navigate } = useRoute();

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', tweaks.theme || 'kleurrijk');
    document.documentElement.setAttribute('data-density', tweaks.density || 'standard');
    document.documentElement.setAttribute('data-bg', tweaks.bg || 'papier');
  }, [tweaks.theme, tweaks.density, tweaks.bg]);

  // herlaadt alle data uit de backend en forceert een re-render
  const reload = React.useCallback(async () => {
    await window.API.herlaad();
    setVersion(v => v + 1);
  }, []);

  const D = window.SW_DATA;
  const { section, id } = route;
  let body = null, title = '', sub = '';

  if (section === 'dashboard') {
    title = 'Dashboard';
    sub = `${D.PROPERTY.name || 'Schoenerweg 1'} · ${D.PROPERTY.address || ''} · ${D.fmtDate(new Date())}`;
    body = <window.Screens.Dashboard navigate={navigate} reload={reload} />;
  } else if (section === 'tenants') {
    if (id) {
      title = 'Huurder';
      sub = D.TENANTS.find(t => t.id === id)?.name || '';
      body = <window.Screens.TenantDetail id={id} navigate={navigate} reload={reload} />;
    } else {
      title = 'Huurders';
      sub = `${D.TENANTS.length} huurders · ${D.fmtEUR(D.MONTHLY_NET)} maandomzet ex btw`;
      body = <window.Screens.TenantsList navigate={navigate} reload={reload} />;
    }
  } else if (section === 'contracts') {
    if (id) {
      title = 'Contract';
      body = <window.Screens.ContractDetail id={id} navigate={navigate} reload={reload} />;
    } else {
      title = 'Contracten';
      sub = 'Lopende huurcontracten';
      body = <window.Screens.Contracts navigate={navigate} reload={reload} />;
    }
  } else if (section === 'invoices') {
    if (id) {
      title = 'Factuur';
      body = <window.Screens.InvoiceDetail id={id} navigate={navigate} reload={reload} />;
    } else {
      title = 'Facturen';
      const open = D.INVOICES.filter(i => i.sent && !i.paid).length;
      sub = `${D.INVOICES.length} facturen · ${open} open`;
      body = <window.Screens.InvoicesList navigate={navigate} reload={reload} />;
    }
  } else if (section === 'maintenance') {
    if (id) {
      title = 'Onderhoudsmelding';
      body = <window.Screens.MaintenanceDetail id={id} navigate={navigate} reload={reload} />;
    } else {
      title = 'Onderhoud';
      const open = D.MAINTENANCE.filter(m => m.status !== 'afgerond').length;
      sub = `${D.MAINTENANCE.length} meldingen · ${open} openstaand`;
      body = <window.Screens.MaintenanceList navigate={navigate} reload={reload} />;
    }
  } else if (section === 'documents') {
    title = 'Documenten';
    sub = `${D.DOCUMENTS.length} bestanden in archief`;
    body = <window.Screens.DocumentsScreen navigate={navigate} reload={reload} />;
  } else if (section === 'operations') {
    title = 'Exploitatie';
    const yrs = D.OPERATIONS.years;
    sub = yrs.length ? `Financieel overzicht ${yrs[0].y} – ${yrs[yrs.length - 1].y}` : 'Financieel overzicht';
    body = <window.Screens.Operations navigate={navigate} />;
  } else if (section === 'settings') {
    title = 'Instellingen';
    sub = 'Pand, bedrijf en facturatie';
    body = <window.Screens.Settings reload={reload} onLogout={onLogout} />;
  } else {
    title = 'Dashboard';
    body = <window.Screens.Dashboard navigate={navigate} reload={reload} />;
  }

  const { Sidebar, Topbar } = window.UI;
  const logoutBtn = (
    <button className="btn btn-sm btn-ghost" onClick={onLogout} title="Uitloggen">
      Uitloggen
    </button>
  );

  return (
    <div className="app" data-screen-label={'app:' + section + (id ? ':detail' : '')}>
      <Sidebar route={section} navigate={navigate} mobileOpen={mobileOpen} setMobileOpen={setMobileOpen} />
      <main className="main">
        <Topbar title={title} sub={sub} setMobileOpen={setMobileOpen}
          zoek={<Zoeken navigate={navigate} />}
          actions={section === 'settings' ? logoutBtn : null} />
        <div className="content">{body}</div>
      </main>

      <window.TweaksPanel title="Tweaks">
        <window.TweakSection label="Achtergrond">
          <window.TweakColor
            label={BG_LABELS[tweaks.bg] || 'Achtergrond'}
            value={BG_SWATCHES[tweaks.bg] || BG_SWATCHES.papier}
            options={Object.values(BG_SWATCHES)}
            onChange={(hex) => {
              const key = Object.keys(BG_SWATCHES).find(k => BG_SWATCHES[k] === hex) || 'papier';
              setTweak('bg', key);
            }}
          />
        </window.TweakSection>
        <window.TweakSection label="Kleurpalet">
          <window.TweakRadio
            label="Stijl"
            value={tweaks.theme}
            options={[
              { value: 'kleurrijk', label: 'Kleurrijk' },
              { value: 'kalm',      label: 'Kalm' },
            ]}
            onChange={(v) => setTweak('theme', v)}
          />
        </window.TweakSection>
        <window.TweakSection label="Tabel-dichtheid">
          <window.TweakRadio
            label="Dichtheid"
            value={tweaks.density}
            options={[
              { value: 'compact',  label: 'Compact' },
              { value: 'standard', label: 'Stndrd' },
              { value: 'roomy',    label: 'Royaal' },
            ]}
            onChange={(v) => setTweak('density', v)}
          />
        </window.TweakSection>
      </window.TweaksPanel>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  Root: bepaalt inlog- vs app-weergave                               */
/* ------------------------------------------------------------------ */
function Root() {
  const [fase, setFase] = useState('checking');

  useEffect(() => {
    let actief = true;
    window.API.me()
      .then(() => window.API.herlaad())
      .then(() => { if (actief) setFase('app'); })
      .catch(() => { if (actief) setFase('login'); });
    const onUnauth = () => { if (actief) setFase('login'); };
    window.addEventListener('sw-unauthorized', onUnauth);
    return () => { actief = false; window.removeEventListener('sw-unauthorized', onUnauth); };
  }, []);

  if (fase === 'checking') return <Splash text="Laden…" />;
  if (fase === 'login') {
    return <window.Screens.Login onLogin={async () => {
      await window.API.herlaad();
      setFase('app');
    }} />;
  }
  return <App onLogout={async () => {
    try { await window.API.logout(); } catch (e) { /* genegeerd */ }
    setFase('login');
  }} />;
}

ReactDOM.createRoot(document.getElementById('root')).render(<Root />);
