import "./polyfills/number-toFixedTrunc";
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App.tsx';
import { Provider } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom';
import { initSentry } from './utils/sentry';

const TAB_ID_KEY = '__vt_tab_id__';
const OPEN_TABS_KEY = '__vt_open_tabs__';
const SECURE_STASH_KEY = '__SECURE_KV_STASH__';
const SECURE_HISTORY_NAMESPACE = '__SECURE_KV__';
const TAB_HEARTBEAT_MS = 5000;
const TAB_STALE_MS = 15000;

type OpenTabMap = Record<string, number>;

const getOpenTabs = (): OpenTabMap => {
  try {
    const rawValue = localStorage.getItem(OPEN_TABS_KEY);
    if (!rawValue) return {};

    const parsed = JSON.parse(rawValue);
    if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
      return {};
    }

    return Object.entries(parsed).reduce<OpenTabMap>((acc, [tabId, lastSeen]) => {
      if (typeof lastSeen === 'number' && Number.isFinite(lastSeen)) {
        acc[tabId] = lastSeen;
      }
      return acc;
    }, {});
  } catch {
    return {};
  }
};

const setOpenTabs = (tabs: OpenTabMap) => {
  if (Object.keys(tabs).length === 0) {
    localStorage.removeItem(OPEN_TABS_KEY);
    return;
  }

  localStorage.setItem(OPEN_TABS_KEY, JSON.stringify(tabs));
};

const resolveClient = () => {
  const params = new URLSearchParams(window.location.search);
  const clientFromQuery = params.get('client') || Array.from(params.keys())[0];
  return clientFromQuery || localStorage.getItem('client_name') || '';
};

const clearPersistedAuth = () => {
  localStorage.clear();
  sessionStorage.removeItem(SECURE_STASH_KEY);
  sessionStorage.removeItem(TAB_ID_KEY);

  const currentHistoryState =
    history.state && typeof history.state === 'object' ? history.state : null;

  if (currentHistoryState && SECURE_HISTORY_NAMESPACE in currentHistoryState) {
    const nextHistoryState = { ...currentHistoryState };
    delete nextHistoryState[SECURE_HISTORY_NAMESPACE];
    history.replaceState(nextHistoryState, document.title);
  }
};

const pruneStaleTabs = (tabs: OpenTabMap, now: number) =>
  Object.entries(tabs).reduce<OpenTabMap>((activeTabs, [tabId, lastSeen]) => {
    if (now - lastSeen <= TAB_STALE_MS) {
      activeTabs[tabId] = lastSeen;
    }
    return activeTabs;
  }, {});

const initializeBrowserCloseLogout = () => {
  const existingTabId = sessionStorage.getItem(TAB_ID_KEY);
  const isExistingTabSession = Boolean(existingTabId);
  const now = Date.now();
  const openTabs = pruneStaleTabs(getOpenTabs(), now);
  setOpenTabs(openTabs);

  if (!isExistingTabSession && Object.keys(openTabs).length === 0) {
    clearPersistedAuth();
  }

  const tabId = existingTabId || crypto.randomUUID();
  sessionStorage.setItem(TAB_ID_KEY, tabId);
  setOpenTabs({
    ...openTabs,
    [tabId]: now,
  });

  const heartbeat = () => {
    const activeTabs = pruneStaleTabs(getOpenTabs(), Date.now());
    activeTabs[tabId] = Date.now();
    setOpenTabs(activeTabs);
  };

  const unregisterTab = () => {
    const activeTabs = pruneStaleTabs(getOpenTabs(), Date.now());
    delete activeTabs[tabId];
    setOpenTabs(activeTabs);
  };

  heartbeat();
  window.setInterval(heartbeat, TAB_HEARTBEAT_MS);
  window.addEventListener('pagehide', unregisterTab);
  window.addEventListener('beforeunload', unregisterTab);
};

// Step 3: Freeze client globally BEFORE React mounts
// This ensures React never re-reads the URL
declare global {
  interface Window {
    __CLIENT__: string;
  }
}
window.__CLIENT__ = resolveClient();
initializeBrowserCloseLogout();

/**
 * Helper to render the app once we have a store instance.
 * Hides the loader (if present) just before rendering.
 */
function renderWithStore(store: any) {
  const loader = document.getElementById('app-loader');
  if (loader) loader.style.display = 'none';

  createRoot(document.getElementById('root')!).render(
    <StrictMode>
      <Router>
        <Provider store={store}>
          <App />
        </Provider>
      </Router>
    </StrictMode>
  );

  // Defer Sentry init so it doesn't block the main thread.
  if ('requestIdleCallback' in window) {
    // @ts-ignore - requestIdleCallback types vary across envs
    requestIdleCallback(() => initSentry(), { timeout: 2000 });
  } else {
    setTimeout(initSentry, 1);
  }
}

/**
 * Initialize secure storage first so decrypted auth/loadState is available to the store.
 * If it succeeds we import/store and render. If it fails, we still import/store and render as fallback.
 */
import('./security/storage-guard')
  .then(async ({ initSecureStorage }) => {
    await initSecureStorage();
    const { store } = await import('./redux/store.ts');
    renderWithStore(store);
  })
  .catch(async (err) => {
    console.error('Failed to initialize secure storage:', err);
    // Fallback — still render the app so users aren't blocked.
    const { store } = await import('./redux/store.ts');
    renderWithStore(store);
  });