/* TRAX — app shell, routing, state orchestration */

const ROUTES = [
  { group: 'Overview', items: [{ key: 'dashboard', label: 'Dashboard', icon: 'dashboard', crumb: 'Overview' }] },
  { group: 'Transactions', items: [
    { key: 'ledger', label: 'Journal Ledger', icon: 'ledger', crumb: 'Transactions' },
    { key: 'accounts', label: 'Chart of Accounts', icon: 'accounts', crumb: 'Transactions' },
  ] },
  { group: 'Reports', items: [
    { key: 'pl', label: 'P&L Statement', icon: 'pl', crumb: 'Reports' },
    { key: 'ie', label: 'Income & Expense', icon: 'ie', crumb: 'Reports' },
    { key: 'bs', label: 'Balance Sheet', icon: 'bs', crumb: 'Reports' },
    { key: 'tb', label: 'Trial Balance', icon: 'tb', crumb: 'Reports' },
  ] },
];
const ROUTE_MAP = {}; ROUTES.forEach(g => g.items.forEach(i => ROUTE_MAP[i.key] = i));

// Bottom nav items: the 5 most important screens (mobile only, < 480px via CSS)
const BOTTOM_NAV = [
  { key: 'dashboard', label: 'Dashboard', icon: 'dashboard' },
  { key: 'ledger', label: 'Ledger', icon: 'ledger' },
  { key: 'accounts', label: 'Accounts', icon: 'accounts' },
  { key: 'pl', label: 'P&L', icon: 'pl' },
  { key: 'bs', label: 'Balance', icon: 'bs' },
];

function App() {
  const S = useStore();
  const [route, setRoute] = useState(() => localStorage.getItem('trax_route') || 'dashboard');
  const [entryModal, setEntryModal] = useState(null);   // {editing} or {} for new, or null
  const [acctModal, setAcctModal] = useState(null);
  const [dsModal, setDsModal] = useState(false);
  const [confirmModal, setConfirmModal] = useState(null); // { message, onConfirm }
  const [sbOpen, setSbOpen] = useState(false);
  const [sync, setSync] = useState({ state: 'idle' });
  const [ready, setReady] = useState(false);
  const importRef = useRef(null);

  const theme = S.prefs.theme || 'dark';
  const currency = S.prefs.currency || 'USD';

  // boot
  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
    TRAX.load().then(() => setReady(true));
    // opts: optional { title, confirmLabel } to reuse the modal beyond deletes
    window.__traxConfirm = (message, onConfirm, opts) => setConfirmModal(Object.assign({ message, onConfirm }, opts));
    // global save fn — persists to Supabase (and the local cache)
    window.__traxSave = async () => {
      setSync({ state: 'syncing' });
      const r = await TRAX.save();
      if (r.committed) { setSync({ state: 'ok' }); toast('Saved to cloud', 'ok'); }
      else if (r.error) { setSync({ state: 'err' }); toast('Save failed: ' + r.error.slice(0, 40), 'err'); }
      else setSync({ state: 'idle' });
      setTimeout(() => setSync(s => (s.state === 'ok' ? { state: 'idle' } : s)), 2200);
    };
  }, []);

  useEffect(() => { document.documentElement.setAttribute('data-theme', theme); }, [theme]);
  useEffect(() => { localStorage.setItem('trax_route', route); }, [route]);

  // autosave to localStorage 2 s after any store change
  useEffect(() => {
    if (!ready) return;
    let timer;
    const unsub = TRAX.subscribe(() => {
      clearTimeout(timer);
      timer = setTimeout(() => TRAX.persistLocal(), 2000);
    });
    return () => { clearTimeout(timer); unsub(); };
  }, [ready]);

  // keyboard: N opens a new entry — but not with modifiers (browser shortcuts
  // like Cmd/Ctrl+N), not while typing, and not while any modal is open
  useEffect(() => {
    const h = e => {
      if (e.metaKey || e.ctrlKey || e.altKey) return;
      if (e.target.matches('input,textarea,select')) return;
      if (document.querySelector('.ov')) return;
      if (e.key === 'n' || e.key === 'N') { e.preventDefault(); setEntryModal({}); }
    };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, []);

  function go(key) { setRoute(key); setSbOpen(false); window.scrollTo(0, 0); }
  const openEntry = (e) => setEntryModal(e ? { editing: e } : {});
  const openAccount = (a) => setAcctModal(a ? { editing: a } : {});

  function onImportFile(ev) {
    const file = ev.target.files && ev.target.files[0];
    ev.target.value = ''; // allow re-selecting the same file later
    if (!file) return;
    window.__traxConfirm(
      'Replace all current data with "' + file.name + '"? A backup of the current data is kept in this browser.',
      () => TRAX.importJSON(file)
        .then(() => toast('Imported ' + TRAX.Store.data.entries.length + ' entries', 'ok'))
        .catch(err => toast(String(err.message || err), 'err')),
      { title: 'Confirm Import', confirmLabel: 'Import' }
    );
  }

  const cur = ROUTE_MAP[route] || ROUTE_MAP.dashboard;

  // source pill
  let pillCls = 'supabase', pillTxt = 'Supabase';
  if (sync.state === 'syncing') { pillCls = 'syncing'; pillTxt = 'Syncing\u2026'; }
  else if (sync.state === 'err') { pillCls = 'err'; pillTxt = 'Sync error'; }
  else if (S.source === 'supabase' && !S.loadWarning) { pillCls = 'supabase'; pillTxt = 'Supabase'; }
  else if (S.source === 'seed') { pillCls = 'seed'; pillTxt = 'FINANCE.xlsx'; }
  else { pillCls = 'local'; pillTxt = 'Local copy'; }

  const screenProps = { S: S.data, currency, go, openEntry, openAccount };

  let screen;
  switch (route) {
    case 'ledger': screen = React.createElement(Ledger, screenProps); break;
    case 'accounts': screen = React.createElement(Accounts, screenProps); break;
    case 'pl': screen = React.createElement(PLReport, screenProps); break;
    case 'ie': screen = React.createElement(IEReport, screenProps); break;
    case 'bs': screen = React.createElement(BSReport, screenProps); break;
    case 'tb': screen = React.createElement(TBReport, screenProps); break;
    default: screen = React.createElement(Dashboard, screenProps);
  }

  return React.createElement('div', { className: 'app' },
    /* sidebar */
    React.createElement('aside', { className: 'sidebar' + (sbOpen ? ' open' : '') },
      React.createElement('div', { className: 'brand' },
        React.createElement('div', { className: 'brand-mark' },
          React.createElement('img', { src: 'LOGO.png', alt: 'TRAX logo' })
        ),
        React.createElement('div', null,
          React.createElement('div', { className: 'brand-name' },
            'KneuraTrax', React.createElement('sup', { className: 'brand-tm' }, '™')),
          React.createElement('div', { className: 'brand-sub' }, 'Financial ledger')
        )
      ),
      React.createElement('nav', null,
        ROUTES.map(g => React.createElement(React.Fragment, { key: g.group },
          React.createElement('div', { className: 'nav-group' }, g.group),
          g.items.map(it => React.createElement('button', {
            key: it.key, className: 'nav-item' + (route === it.key ? ' active' : ''), onClick: () => go(it.key),
          }, React.createElement(Icon, { name: it.icon, w: 15 }), it.label))
        ))
      ),
      React.createElement('div', { className: 'sb-foot' },
        React.createElement('span', { className: 'dot', style: { width: 6, height: 6, borderRadius: '50%', background: 'var(--pos)' } }),
        S.data.entries.length + ' entries \u00b7 ' + S.data.accounts.length + ' accts'
      )
    ),
    React.createElement('div', { className: 'scrim' + (sbOpen ? ' show' : ''), onClick: () => setSbOpen(false) }),

    /* main */
    React.createElement('div', { className: 'main' },
      React.createElement('div', { className: 'topbar' },
        React.createElement('button', { className: 'icobtn hamburger', onClick: () => setSbOpen(true) }, React.createElement(Icon, { name: 'menu', w: 16 })),
        /* Brand mark — shown only when the persistent sidebar is not visible */
        React.createElement('div', { className: 'tb-brand' },
          React.createElement('div', { className: 'tb-brand-mark' },
            React.createElement('img', { src: 'LOGO.png', alt: 'KneuraTrax' })
          ),
          React.createElement('div', null,
            React.createElement('div', { className: 'tb-brand-name' },
              'KneuraTrax', React.createElement('sup', { className: 'brand-tm' }, '™')
            ),
            React.createElement('div', { className: 'tb-brand-sub' }, 'Financial Ledger')
          )
        ),
        React.createElement('div', { className: 'tb-title' },
          React.createElement('div', { className: 'tb-crumb' }, cur.crumb),
          React.createElement('div', { className: 'tb-h1' }, cur.label)
        ),
        React.createElement('div', { className: 'tb-spacer' }),
        React.createElement('div', { className: 'tb-actions' },
          /* currency */
          React.createElement('div', { className: 'seg' },
            [['USD', '$'], ['INR', '₹']].map(([c, sym]) => React.createElement('button', {
              key: c, className: currency === c ? 'on accent' : '', onClick: () => TRAX.setPref('currency', c),
            },
              React.createElement('span', { className: 'cur-full' }, c),
              React.createElement('span', { className: 'cur-sym' }, sym)
            ))
          ),
          /* source pill */
          React.createElement('button', { className: 'pill ' + pillCls, onClick: () => setDsModal(true), title: S.loadWarning ? 'Data source — ' + S.loadWarning : 'Data source' },
            React.createElement('span', { className: 'dot' }), pillTxt, S.loadWarning && ' ⚠'),
          /* theme */
          React.createElement('button', { className: 'icobtn', 'data-tip': theme === 'dark' ? 'Light mode' : 'Dark mode', onClick: () => TRAX.setPref('theme', theme === 'dark' ? 'light' : 'dark') },
            React.createElement(Icon, { name: theme === 'dark' ? 'sun' : 'moon', w: 15 })),
          /* export \u2014 hidden on very small screens */
          React.createElement('button', { className: 'icobtn', 'data-tip': 'Export FINANCE.xlsx', onClick: () => { TRAX.exportJSON(); toast('Downloaded FINANCE.xlsx', 'ok'); } },
            React.createElement(Icon, { name: 'download', w: 15 })),
          /* import \u2014 replaces current data after confirmation */
          React.createElement('input', { ref: importRef, type: 'file', accept: '.json,.xlsx,application/json', style: { display: 'none' }, onChange: onImportFile }),
          React.createElement('button', { className: 'icobtn', 'data-tip': 'Import FINANCE.xlsx', onClick: () => importRef.current && importRef.current.click() },
            React.createElement(Icon, { name: 'upload', w: 15 })),
          /* save */
          React.createElement('button', {
            className: 'icobtn' + (sync.state === 'ok' ? ' save-ok' : ''),
            'data-tip': sync.state === 'syncing' ? 'Saving\u2026' : sync.state === 'ok' ? 'Saved!' : 'Save',
            disabled: sync.state === 'syncing',
            onClick: () => window.__traxSave('Manual save'),
          }, React.createElement(Icon, { name: sync.state === 'syncing' ? 'refresh' : 'save', w: 15 })),
          /* new */
          React.createElement('button', { className: 'btn btn-accent btn-sm', onClick: () => setEntryModal({}) },
            React.createElement(Icon, { name: 'plus', w: 14 }),
            React.createElement('span', { className: 'btn-new-label' }, 'New'))
        )
      ),
      React.createElement('div', { className: 'content', key: route, 'data-screen-label': cur.label }, screen)
    ),

    /* bottom nav \u2014 visible only on mobile (< 480px via CSS) */
    React.createElement('nav', { className: 'bottom-nav' },
      React.createElement('div', { className: 'bottom-nav-inner' },
        BOTTOM_NAV.map(it => React.createElement('button', {
          key: it.key, className: 'bn-item' + (route === it.key ? ' active' : ''), onClick: () => go(it.key),
        }, React.createElement(Icon, { name: it.icon, w: 18 }), it.label))
      )
    ),

    /* modals */
    entryModal && React.createElement(EntryModal, { editing: entryModal.editing, onClose: () => setEntryModal(null) }),
    acctModal && React.createElement(AccountModal, { editing: acctModal.editing, onClose: () => setAcctModal(null) }),
    dsModal && React.createElement(DataSourceModal, { onClose: () => setDsModal(false) }),
    confirmModal && React.createElement(ConfirmModal, Object.assign({}, confirmModal, { onClose: () => setConfirmModal(null) })),
    React.createElement(Toast, null)
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(React.createElement(App));
