// app.jsx — main app

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": ["#FDF8F3", "#3B1F0A", "#D4607A", "#4CAF82"],
  "density": "regular",
  "fontpair": "editorial"
}/*EDITMODE-END*/;

const PALETTE_OPTIONS = [
  ['#FDF8F3', '#3B1F0A', '#D4607A', '#4CAF82'],
  ['#F4F1EC', '#1B1612', '#C04A6D', '#2E8C66'],
  ['#FFF6EC', '#3D1A1A', '#E36A4F', '#5C9A4F'],
  ['#F2EDE4', '#2A2A2A', '#7A4A8A', '#4F8C7A'],
];

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  React.useEffect(() => {
    const [bg, ink, rose, green] = t.palette;
    const root = document.documentElement;
    root.style.setProperty('--cream', bg);
    root.style.setProperty('--ink', ink);
    root.style.setProperty('--rose', rose);
    root.style.setProperty('--green', green);
    root.style.setProperty('--cream-2', mix(bg, ink, 0.04));
    root.style.setProperty('--cream-3', mix(bg, ink, 0.10));
    root.style.setProperty('--ink-2', mix(ink, bg, 0.18));
    root.style.setProperty('--ink-3', mix(ink, bg, 0.42));
    root.style.setProperty('--ink-mute', mix(ink, bg, 0.45));
    root.style.setProperty('--line', hexA(ink, 0.10));
    root.style.setProperty('--line-2', hexA(ink, 0.22));
    root.style.setProperty('--rose-soft', mix(rose, bg, 0.75));
    root.style.setProperty('--green-soft', mix(green, bg, 0.78));
    document.body.dataset.density = t.density;
    document.body.dataset.fontpair = t.fontpair;
  }, [t]);

  // ── Auth ─────────────────────────────────────────────────
  const [user, setUser] = React.useState(null);
  const [authChecked, setAuthChecked] = React.useState(false);

  const logout = React.useCallback(() => {
    window.api.clearToken();
    setUser(null);
  }, []);

  React.useEffect(() => {
    window.api.me().then(u => { if (u) setUser(u); }).finally(() => setAuthChecked(true));
  }, []);

  // Redirect to login immediately when any request returns 401
  React.useEffect(() => {
    window.addEventListener('auth:expired', logout);
    return () => window.removeEventListener('auth:expired', logout);
  }, [logout]);

  // Proactive: 2 min before expiry, refresh if the user made a request recently;
  // otherwise log out. Rescheduled after each successful refresh.
  const tokenTimerRef = React.useRef(null);
  const scheduleTokenRefresh = React.useCallback(() => {
    clearTimeout(tokenTimerRef.current);
    const exp = window.api.getTokenExpiry();
    if (!exp) return;
    // Fire 2 minutes before the token expires
    const delay = Math.max(0, exp - Date.now() - 2 * 60 * 1000);
    tokenTimerRef.current = setTimeout(async () => {
      const idleMs = Date.now() - window.api.getLastRequestAt();
      if (idleMs < 10 * 60 * 1000) {
        // Active in the last 10 min — refresh and reschedule
        try {
          await window.api.refreshToken();
          scheduleTokenRefresh();
        } catch {
          logout();
        }
      } else {
        logout();
      }
    }, delay);
  }, [logout]);

  React.useEffect(() => {
    if (!user) return;
    scheduleTokenRefresh();
    return () => clearTimeout(tokenTimerRef.current);
  }, [user, scheduleTokenRefresh]);

  // ── State ────────────────────────────────────────────────
  const [orders, setOrders] = React.useState([]);
  const [staff, setStaff] = React.useState([]);
  const [flavours, setFlavours] = React.useState([]);
  const [corrections, setCorrections] = React.useState([]);
  const [notifications, setNotifications] = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const [modelMeta, setModelMeta] = React.useState({
    version: 6, lastTrained: '3 days ago', mae: '2.40', imageCount: 64, corrections: 4,
  });
  const [notifyConfig, setNotifyConfig] = React.useState({
    phone: '', inApp: true, waEnabled: false, waCallmebotKey: '',
  });
  const [pricingConfig, setPricingConfig] = React.useState({
    diameters: [10, 12, 14],
    personSizes: [...window.PERSON_SIZES],
    basePrices: { ...window.BASE_PRICES },
  });
  const [shopConfig, setShopConfig] = React.useState({ daysAhead: 30, staffSeePastOrders: true });
  const [baklavaPricing, setBaklavaPricing] = React.useState({ tepsi: 40, kg: 10 });
  const [fridgeConfig, setFridgeConfig] = React.useState({ multiFridge: false, fridges: [] });

  // ── Load data after login ─────────────────────────────────
  const [refreshing, setRefreshing] = React.useState(false);

  const loadData = React.useCallback((showSpinner = true) => {
    if (!user) return;
    if (showSpinner) setLoading(true);
    else setRefreshing(true);
    const isOwner = user.role === 'owner';
    Promise.all([
      window.api.getOrders(),
      isOwner ? window.api.getStaff() : Promise.resolve([]),
      window.api.getFlavours(),
      isOwner ? window.api.getCorrections() : Promise.resolve([]),
      window.api.getNotifications(),
      window.api.getSettings(),
    ]).then(([ord, stf, flv, corr, notif, settings]) => {
      setOrders(ord);
      setStaff(stf);
      setFlavours(flv);
      setCorrections(corr);
      setNotifications(notif);
      setBaklavaPricing({
        tepsi: parseFloat(settings.baklava_tepsi_price) || 40,
        kg: parseFloat(settings.baklava_kg_price) || 10,
      });
      setPricingConfig({
        diameters: (() => { try { return JSON.parse(settings.cake_diameters || ''); } catch { return [10, 12, 14]; } })(),
        personSizes: (() => { try { return JSON.parse(settings.cake_person_sizes || ''); } catch { return [...window.PERSON_SIZES]; } })(),
        basePrices: (() => { try { return JSON.parse(settings.cake_base_prices || ''); } catch { return { ...window.BASE_PRICES }; } })(),
      });
      setFridgeConfig({
        multiFridge: settings.multi_fridge_enabled === '1',
        fridges: (() => { try { return JSON.parse(settings.fridges || '[]'); } catch { return []; } })(),
      });
      setNotifyConfig(prev => ({
        ...prev,
        phone: settings.notify_phone || prev.phone,
        waEnabled: settings.whatsapp_notifications_enabled === '1',
        waCallmebotKey: settings.whatsapp_callmebot_key || '',
      }));
    }).catch(err => {
      console.error('Failed to load data:', err);
    }).finally(() => { setLoading(false); setRefreshing(false); });
  }, [user]);

  React.useEffect(() => { loadData(true); }, [user]);

  // ── Service worker registration ───────────────────────────────────────
  React.useEffect(() => {
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/sw.js').catch(() => {});
    }
  }, []);

  // ── Background poll for new orders ───────────────────────────────────
  const [pendingOrders, setPendingOrders] = React.useState(0);
  const knownIdsRef = React.useRef(new Set());

  // Keep known IDs in sync whenever orders load
  React.useEffect(() => {
    orders.forEach(o => knownIdsRef.current.add(o.id));
  }, [orders]);

  React.useEffect(() => {
    if (!user) return;
    const poll = async () => {
      try {
        const fresh = await window.api.getOrders();
        const unseen = fresh.filter(o => !knownIdsRef.current.has(o.id));
        if (unseen.length > 0) setPendingOrders(p => p + unseen.length);
      } catch {}
    };
    const id = setInterval(poll, 30000);
    return () => clearInterval(id);
  }, [user]);

  const acceptPending = React.useCallback(() => {
    setPendingOrders(0);
    loadData(false);
  }, [loadData]);

  // ── Navigation ───────────────────────────────────────────
  const [route, _setRoute] = React.useState({ name: 'orders' });

  const setRoute = React.useCallback((newRoute) => {
    history.pushState({ route: newRoute }, '');
    _setRoute(newRoute);
  }, []);

  React.useEffect(() => {
    history.replaceState({ route: { name: 'orders' } }, '');
    const onPop = (e) => _setRoute(e.state?.route ?? { name: 'orders' });
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, []);
  const [filter, setFilter] = React.useState('all');
  const [search, setSearch] = React.useState('');
  const [dateFilter, setDateFilter] = React.useState('all');
  const [notifOpen, setNotifOpen] = React.useState(false);
  const [toast, setToast] = React.useState(null);
  const addToast = (message) => setToast({ message, id: Date.now() });

  // ── Mutators ─────────────────────────────────────────────
  const updateOrder = (id, patch) => {
    window.api.updateOrder(id, patch).then(updated => {
      setOrders(prev => prev.map(o => o.id === id ? updated : o));
      if (patch._correction) {
        window.api.getCorrections().then(setCorrections).catch(() => {});
      }
    }).catch(() => addToast('Ndryshimet nuk u ruajtën'));
  };

  const deleteOrder = (id) => {
    window.api.deleteOrder(id).then(() => {
      setOrders(prev => prev.filter(o => o.id !== id));
      setRoute({ name: 'orders' });
    }).catch(() => addToast('Porosia nuk u fshi'));
  };

  const createOrder = (order) => {
    window.api.createOrder(order).then(created => {
      setOrders(prev => [created, ...prev]);
      setRoute({ name: 'orderDetail', id: created.id });
    }).catch(() => addToast('Porosia nuk u krijua'));
  };

  window.__app_accept_ai = (id) => {
    const order = orders.find(o => o.id === id);
    if (!order) return;
    updateOrder(id, { payment: { total_price: order.ai?.predicted_price } });
    addToast('Çmimi u pranua nga parashikimi i AI');
  };

  // ── Render ───────────────────────────────────────────────
  if (!authChecked) return (
    <div style={{ minHeight: '100vh', display: 'grid', placeItems: 'center', background: 'var(--cream)' }}>
      <span className="spinner lg" style={{ borderColor: 'rgba(59,31,10,0.15)', borderTopColor: 'var(--rose)' }} />
    </div>
  );
  if (!user) return <LoginScreen onLogin={setUser} />;

  if (loading) {
    return (
      <div style={{ minHeight: '100vh', display: 'grid', placeItems: 'center', background: 'var(--cream)' }}>
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16 }}>
          <span className="spinner lg" style={{ borderColor: 'rgba(59,31,10,0.15)', borderTopColor: 'var(--rose)' }} />
          <span className="muted" style={{ fontSize: 14 }}>Duke ngarkuar…</span>
        </div>
      </div>
    );
  }

  const unreadNotifications = notifications.filter(n => !n.is_read).length;
  const visibleOrders = user?.role === 'owner'
    ? orders
    : orders.filter(o => {
        const diff = (new Date(o.due_date) - new Date('2026-05-13')) / 86400000;
        if (diff > shopConfig.daysAhead) return false;
        if (!shopConfig.staffSeePastOrders && (o.status === 'delivered' || o.status === 'cancelled')) return false;
        return true;
      });
  const due = orders.filter(o =>
    (window.relativeDay(o.due_date) === 'Sot' || window.relativeDay(o.due_date) === 'Nesër') &&
    o.status !== 'delivered' && o.status !== 'cancelled'
  );
  const currentOrder = route.name === 'orderDetail' ? orders.find(o => o.id === route.id) : null;

  let pageTitle = 'Porosi'; let pageCrumb = 'Punëtoria';
  if (route.name === 'payments')                          { pageTitle = 'Pagesa';      pageCrumb = 'Financat'; }
  else if (route.name === 'settings')                     { pageTitle = 'Cilësimet';   pageCrumb = 'Konfiguro'; }
  else if (route.name === 'stats')                        { pageTitle = 'Statistika';  pageCrumb = 'Pasqyra'; }
  else if (route.name === 'newOrder')                     { pageTitle = 'Porosi e re'; pageCrumb = 'Porosi'; }
  else if (route.name === 'orderDetail' && currentOrder)  { pageTitle = currentOrder.customer_name; pageCrumb = `Porosia #${currentOrder.id.slice(-4)}`; }

  const markAllRead = () => {
    window.api.markAllNotifRead().catch(() => {});
    setNotifications(prev => prev.map(n => ({ ...n, is_read: true })));
  };

  return (
    <div id="app" className="paper-bg">
      <aside className="sidebar">
        <div className="brand">
          <div className="brand-mark">
            <PastericaLogo size={20} color="var(--cream)" />
          </div>
          <div>
            <div className="brand-name">Sistemi</div>
            <div className="brand-sub">Internal · Vetëm për stafin</div>
          </div>
        </div>
        <NavItem icon={IconCake} label="Porosi" active={route.name === 'orders' || route.name === 'orderDetail' || route.name === 'newOrder'} badge={due.length}
                 onClick={() => setRoute({ name: 'orders' })} />
        {user.role === 'owner' && (
          <NavItem icon={IconBarChart} label="Statistika" active={route.name === 'stats'}
                   onClick={() => setRoute({ name: 'stats' })} />
        )}
        <NavItem icon={IconSparkle} label="Çmimet" active={route.name === 'pricing'}
                 onClick={() => { setRoute({ name: 'orders' }); setFilter('custom'); }} />
        {user.role === 'owner' && (
          <NavItem icon={IconReceipt} label="Pagesa" active={route.name === 'payments'}
                   onClick={() => setRoute({ name: 'payments' })} />
        )}
        <NavItem icon={IconSettings} label="Cilësimet" active={route.name === 'settings'}
                 onClick={() => setRoute({ name: 'settings' })} />
        <div className="sidebar-foot">
          <Avatar name={user.name} color={user.color} />
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontWeight: 600, fontSize: 13.5 }}>{user.name}</div>
            <div className="muted" style={{ fontSize: 11.5 }}>@{user.username} · {user.role}</div>
          </div>
          <button className="icon-btn" onClick={() => { logout(); }} title="Dil" style={{ width: 32, height: 32 }}>
            <IconLogout size={16} />
          </button>
        </div>
      </aside>

      <div className="main">
        <header className="topbar">
          <div style={{ minWidth: 0, flex: 1 }}>
            <div className="crumbs">{pageCrumb}</div>
            <h1>{pageTitle}</h1>
          </div>
          <div className="topbar-actions" style={{ position: 'relative' }}>
            <button className="icon-btn" onClick={() => loadData(false)} disabled={refreshing} title="Rifresko" style={{ width: 36, height: 36 }}>
              <IconRefresh size={17} style={{ transition: 'transform 0.6s', transform: refreshing ? 'rotate(360deg)' : 'none' }} />
            </button>
            <NotificationBell count={unreadNotifications} active={notifOpen} onClick={() => setNotifOpen(!notifOpen)} />
            <button className="icon-btn mobile-only" onClick={() => { logout(); }} title="Dil">
              <IconLogout size={17} />
            </button>
            {notifOpen && (
              <NotificationsPanel
                notifications={notifications}
                onClose={() => setNotifOpen(false)}
                onMarkAllRead={markAllRead}
                onOpen={(id) => { setRoute({ name: 'orderDetail', id }); setNotifOpen(false); }}
                onGoToHistory={() => setRoute({ name: 'settings', sub: 'notif_history' })}
              />
            )}
          </div>
        </header>

        <main className="scroll-area">
          {route.name === 'orders' && (
            <OrdersList orders={visibleOrders} onOpen={(id) => setRoute({ name: 'orderDetail', id })}
                        onNew={() => setRoute({ name: 'newOrder' })}
                        search={search} setSearch={setSearch}
                        filter={filter} setFilter={setFilter}
                        dateFilter={dateFilter} setDateFilter={setDateFilter}
                        currentUser={user}
                        pendingOrders={pendingOrders} onAcceptPending={acceptPending} />
          )}
          {route.name === 'orderDetail' && currentOrder && (
            <OrderDetail order={currentOrder} currentUser={user}
              onBack={() => setRoute({ name: 'orders' })}
              onUpdate={updateOrder} onDelete={deleteOrder} addToast={addToast}
              fridgeConfig={fridgeConfig}
              flavours={flavours} pricingConfig={pricingConfig} baklavaPricing={baklavaPricing} />
          )}
          {route.name === 'newOrder' && (
            <NewOrder onCreate={createOrder} onCancel={() => setRoute({ name: 'orders' })} addToast={addToast} flavours={flavours} pricingConfig={pricingConfig} baklavaPricing={baklavaPricing} orders={orders} />
          )}
          {route.name === 'stats' && user.role === 'owner' && (
            <StatsScreen orders={visibleOrders} />
          )}
          {route.name === 'payments' && (
            <PaymentsScreen orders={orders} currentUser={user}
                            onOpenOrder={(id) => setRoute({ name: 'orderDetail', id })} />
          )}
          {route.name === 'settings' && (
            <SettingsScreen
              currentUser={user}
              staff={staff} setStaff={setStaff}
              flavours={flavours} setFlavours={setFlavours}
              corrections={corrections}
              modelMeta={modelMeta} setModelMeta={setModelMeta}
              notifyConfig={notifyConfig} setNotifyConfig={setNotifyConfig}
              pricingConfig={pricingConfig} setPricingConfig={setPricingConfig}
              shopConfig={shopConfig} setShopConfig={setShopConfig}
              baklavaPricing={baklavaPricing} setBaklavaPricing={setBaklavaPricing}
              fridgeConfig={fridgeConfig} setFridgeConfig={setFridgeConfig}
              notifications={notifications} onMarkAllNotifRead={markAllRead}
              onOpenOrder={(id) => setRoute({ name: 'orderDetail', id })}
              initialSub={route.sub}
              addToast={addToast}
              onOrdersCleared={() => setOrders([])}
              onCorrectionsCleared={() => setCorrections([])}
            />
          )}
        </main>

        <nav className="bottom-nav">
          <NavItem icon={IconCake} label="Porosi" active={route.name === 'orders' || route.name === 'orderDetail' || route.name === 'newOrder'}
                   onClick={() => setRoute({ name: 'orders' })} />
          {user.role === 'owner' && (
            <NavItem icon={IconBarChart} label="Statistika" active={route.name === 'stats'}
                     onClick={() => setRoute({ name: 'stats' })} />
          )}
          {user.role === 'owner' && (
            <NavItem icon={IconReceipt} label="Pagesa" active={route.name === 'payments'}
                     onClick={() => setRoute({ name: 'payments' })} />
          )}
          <NavItem icon={IconSettings} label="Cilësimet" active={route.name === 'settings'}
                   onClick={() => setRoute({ name: 'settings' })} />
        </nav>
      </div>

      <Toast toast={toast} onDismiss={() => setToast(null)} />

      <TweaksPanel title="Tweaks">
        <TweakSection label="Palette">
          <TweakColor label="Theme" value={t.palette} options={PALETTE_OPTIONS}
                      onChange={(v) => setTweak('palette', v)} />
        </TweakSection>
        <TweakSection label="Density">
          <TweakRadio label="Density" value={t.density}
                      options={['compact', 'regular', 'comfy']}
                      onChange={(v) => setTweak('density', v)} />
        </TweakSection>
        <TweakSection label="Typography">
          <TweakSelect label="Font pairing" value={t.fontpair}
                       options={[
                         { value: 'editorial', label: 'Editorial · Playfair + Inter' },
                         { value: 'modern', label: 'Modern · Fraunces + DM Sans' },
                         { value: 'warm', label: 'Warm · Instrument + Manrope' },
                         { value: 'utility', label: 'Utility · Space Grotesk + Inter' },
                       ]}
                       onChange={(v) => setTweak('fontpair', v)} />
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

function NavItem({ icon: I, label, active, onClick, badge }) {
  return (
    <button className={`nav-item ${active ? 'active' : ''}`} onClick={onClick}>
      <span className="nav-icon">
        <I size={20} color="currentColor" />
      </span>
      <span>{label}</span>
      {badge > 0 && <span className="nav-badge">{badge}</span>}
    </button>
  );
}

function NotificationsPanel({ notifications, onClose, onMarkAllRead, onOpen, onGoToHistory }) {
  const unread = notifications.filter(n => !n.is_read);
  return (
    <>
      <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 50 }} />
      <div className="notif-panel">
        <div style={{ padding: '14px 18px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderBottom: '1px solid var(--line)' }}>
          <div>
            <h3 className="display" style={{ margin: 0, fontSize: 18, fontWeight: 600 }}>Njoftime</h3>
            <span className="muted" style={{ fontSize: 12 }}>{unread.length} të palexuara</span>
          </div>
          {unread.length > 0 && <button className="chip" style={{ height: 28, fontSize: 12 }} onClick={onMarkAllRead}>Shëno të gjitha</button>}
        </div>
        <div style={{ maxHeight: 380, overflowY: 'auto' }}>
          {unread.length === 0 ? (
            <p className="muted" style={{ padding: 24, textAlign: 'center', margin: 0 }}>Asnjë njoftim i palexuar.</p>
          ) : unread.map(n => (
            <div key={n.id} onClick={() => { n.order_id && onOpen(n.order_id); }} style={{
              padding: '14px 18px', cursor: n.order_id ? 'pointer' : 'default',
              borderBottom: '1px solid var(--line)',
              background: 'var(--cream-2)',
              display: 'flex', gap: 12,
            }}>
              <div style={{ width: 32, height: 32, borderRadius: 8, flexShrink: 0, display: 'grid', placeItems: 'center', background: kindBg(n.kind) }}>
                {kindIcon(n.kind)}
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 14, fontWeight: 600, lineHeight: 1.35 }}>{n.message}</div>
                <div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>{n.created_at}</div>
              </div>
              <div style={{ width: 8, height: 8, background: 'var(--rose)', borderRadius: '50%', flexShrink: 0, marginTop: 6 }} />
            </div>
          ))}
        </div>
        <button onClick={() => { onClose(); onGoToHistory(); }} style={{
          width: '100%', padding: '12px 18px', background: 'none', border: 'none',
          borderTop: '1px solid var(--line)', cursor: 'pointer',
          fontSize: 13, color: 'var(--ink-mute)', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
        }}>
          Shiko historikun e plotë <IconChevronRight size={13} color="var(--ink-mute)" />
        </button>
      </div>
    </>
  );
}

window.kindBg = function kindBg(kind) {
  return {
    due_today:    'var(--red-soft)',
    due_tomorrow: 'var(--amber-soft)',
    correction:   'var(--cream-2)',
    training:     'var(--green-soft)',
    new_order:    'var(--rose-soft)',
    order_ready:  'var(--green-soft)',
  }[kind] || 'var(--cream-2)';
}
window.kindIcon = function kindIcon(kind) {
  const map = {
    due_today:    <IconAlertCircle size={16} color="#8c2e2e" />,
    due_tomorrow: <IconClock size={16} color="#7a5418" />,
    correction:   <IconSparkle size={16} color="var(--ink)" />,
    training:     <IconBrain size={16} color="#285d3f" />,
    new_order:    <IconCake size={16} color="var(--rose)" />,
    order_ready:  <IconCircleCheck size={16} color="#285d3f" />,
  };
  return map[kind] || <IconBell size={16} />;
}

function hexToRgb(hex) {
  const h = hex.replace('#', '');
  const v = h.length === 3 ? h.split('').map(c => c + c).join('') : h;
  const n = parseInt(v, 16);
  return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
}
function rgbToHex([r, g, b]) {
  return '#' + [r, g, b].map(x => Math.round(x).toString(16).padStart(2, '0')).join('');
}
function mix(a, b, w) {
  const ra = hexToRgb(a); const rb = hexToRgb(b);
  return rgbToHex(ra.map((v, i) => v * (1 - w) + rb[i] * w));
}
function hexA(hex, a) {
  const [r, g, b] = hexToRgb(hex);
  return `rgba(${r}, ${g}, ${b}, ${a})`;
}

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