import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'
import { isReadChannel, isNoQueueChannel, cacheRead, getCachedRead, enqueueWrite, drainOutbox } from './lib/offlineStore'

// Determine API base URL dynamically.
// أولوية: تجاوز وقت التشغيل (يحقنه Electron عند التشغيل المحلي) ← متغيّر البناء ← الأصل نفسه.
const RUNTIME_API = (window as any).__SUPERCORE_API__
  || (() => { try { return new URLSearchParams(location.search).get('api') || ''; } catch { return ''; } })()
  || (() => { try { return localStorage.getItem('supercore.apiBase') || ''; } catch { return ''; } })();
try { if (RUNTIME_API) localStorage.setItem('supercore.apiBase', RUNTIME_API); } catch { /* ignore */ }
const API_BASE = RUNTIME_API || import.meta.env.VITE_API_URL || (
  import.meta.env.PROD
    ? '' // In production (Vercel), use relative paths (same origin)
    : 'http://127.0.0.1:3000' // In dev, use the local server (127.0.0.1 is more reliable on Windows)
);

// Channels that only make sense on the machine itself (printing, cash drawer,
// local network middleware) or that talk to the local SQLite database (added
// incrementally as main/localHandlers.cjs implements them) — routed straight to
// the real Electron IPC bridge (preload.cjs → __electronNative) when running as
// the desktop app, bypassing the cloud fetch shim below entirely. In the browser
// (no __electronNative), these simply aren't available — callers already treat
// a failed/empty result as "not supported here".
const NATIVE_CHANNELS = new Set([
  // Hardware/local-network — main.cjs only.
  'print-silent', 'list-printers', 'open-cash-drawer',
  'sync-full-device-list-to-middleware', 'get-middleware-status', 'test-device-connection',
  // Local-first data (main/localHandlers.cjs) — patients + orders/results/payments
  // checkpoint. Reads/writes hit the local SQLite DB directly, no cloud round-trip;
  // a sync engine (later) drains main/localDb.cjs's `sync_queue` to the cloud.
  'get-patients', 'register-patient', 'search-existing-patient', 'update-patient',
  'delete-patient', 'delete-patients',
  'register-and-order', 'create-order', 'get-orders', 'get-active-order',
  'get-order-details', 'get-order-payment-summary', 'record-payment',
  'update-test-result', 'set-test-review', 'save-order-note', 'cancel-order',
  'delete-order', 'update-order',
]);

// Global Electron mock to bridge the desktop app to the web server API
if (!(window as any).electron) {

  (window as any).electron = {
    ipcRenderer: {
      invoke: async (channel: string, ...args: any[]) => {
        const native = (window as any).__electronNative;
        if (native && NATIVE_CHANNELS.has(channel)) {
          return native.ipcRenderer.invoke(channel, ...args);
        }

        // Special handling for browser-based file downloads
        if (channel === 'save-pdf-file') {
          const { base64Data, fileName } = args[0] || {};
          if (base64Data) {
            const link = document.createElement('a');
            link.href = `data:application/pdf;base64,${base64Data}`;
            link.download = fileName || 'document.pdf';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            return { success: true };
          }
        }

        const token = localStorage.getItem('token');

        try {
          const res = await fetch(`${API_BASE}/api/ipc`, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              'Authorization': token ? `Bearer ${token}` : ''
            },
            body: JSON.stringify({ channel, args })
          });

          if (res.ok) {
            const wasOffline = (window as any)._supercore_offline === true;
            (window as any)._supercore_offline = false;
            window.dispatchEvent(new CustomEvent('supercore:server-health', { detail: { connected: true } }));
            // عاد الاتصال → أفرغ الصندوق الصادر (المعاملات المؤجَّلة) على السحابة
            if (wasOffline) drainOutbox(postToCloud);
          }

          if (res.status === 401) {
            localStorage.removeItem('user');
            localStorage.removeItem('token');
            window.location.href = '/login';
            throw new Error('Unauthorized');
          }
          if (!res.ok) throw new Error(`IPC mapped fetch failed: ${res.statusText}`);
          const json = await res.json();
          // خزّن نتائج القراءة الناجحة للاستخدام دون اتصال
          if (isReadChannel(channel)) cacheRead(channel, args, json);
          return json;
        } catch (err: any) {
          const isNetErr = err.message === 'Failed to fetch' || err.message.includes('network') || err.message.includes('NetworkError');
          if (isNetErr) {
            const wasOffline = (window as any)._supercore_offline === true;
            (window as any)._supercore_offline = true;
            (window as any)._supercore_last_offline = Date.now();
            window.dispatchEvent(new CustomEvent('supercore:server-health', { detail: { connected: false } }));
            if (!wasOffline) console.warn('[SuperCore] Offline — using local cache & outbox. Will sync on reconnect.');

            // قراءة: أعِد من الكاش المحلي إن وُجد
            if (isReadChannel(channel)) {
              const cached = await getCachedRead(channel, args);
              if (cached !== undefined) return { ...cached, _fromCache: true };
              return { success: false, error: 'Offline (no cached data)', isOffline: true };
            }
            // كتابة قابلة للتأجيل: ضعها في الصندوق الصادر وأعِد نجاحاً متفائلاً
            if (!isNoQueueChannel(channel)) {
              await enqueueWrite(channel, args);
              return { success: true, queued: true, isOffline: true, message: 'سيُزامَن تلقائياً عند عودة الاتصال' };
            }
            // مصادقة/طباعة: لا تؤجَّل
            return { success: false, error: 'Network Error', isOffline: true };
          }
          console.error(`[Web Mode] IPC Error [Channel: ${channel}]:`, err);
          throw err;
        }
      }
    }
  };

  // دالة الإرسال المستخدمة عند تفريغ الصندوق الصادر بعد عودة الاتصال
  async function postToCloud(channel: string, args: any[]): Promise<{ ok: boolean }> {
    const token = localStorage.getItem('token');
    try {
      const res = await fetch(`${API_BASE}/api/ipc`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': token ? `Bearer ${token}` : '' },
        body: JSON.stringify({ channel, args })
      });
      return { ok: res.ok };
    } catch { return { ok: false }; }
  }

  // حاول تفريغ الصندوق الصادر دورياً (كل 20 ثانية) وعند عودة اتصال الشبكة
  const tryDrain = () => { if (navigator.onLine) drainOutbox(postToCloud); };
  window.addEventListener('online', tryDrain);
  setInterval(tryDrain, 20000);
  setTimeout(tryDrain, 4000);
}

import { BranchProvider } from './context/BranchContext.tsx'
import { LanguageProvider } from './context/LanguageContext.tsx'
import { ThemeProvider } from './context/ThemeContext.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <ThemeProvider>
      <LanguageProvider>
        <BranchProvider>
          <App />
        </BranchProvider>
      </LanguageProvider>
    </ThemeProvider>
  </StrictMode>,
)
