import React, { useState, useEffect, useCallback } from 'react';
import ReactDOM from 'react-dom/client';
import { LogtoProvider, useLogto } from '@logto/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { BrowserRouter } from 'react-router';
import { ThemeProvider, ToastProvider, BreadcrumbProvider, GlobalFilterProvider, Spinner } from '@cameleer/design-system';
import '@cameleer/design-system/style.css';
import { AppRouter } from './router';
import { fetchConfig } from './config';
import { setTokenProvider, setLogoutHandler } from './api/client';

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: 1,
      staleTime: 10_000,
    },
  },
});

function TokenSync({ resource }: { resource: string }) {
  const { getAccessToken, isAuthenticated, signOut } = useLogto();

  useEffect(() => {
    if (isAuthenticated && resource) {
      setTokenProvider(() => getAccessToken(resource));
    } else {
      setTokenProvider(null);
    }
  }, [isAuthenticated, getAccessToken, resource]);

  const handleLogout = useCallback(() => {
    signOut(window.location.origin + '/login');
  }, [signOut]);

  useEffect(() => {
    setLogoutHandler(handleLogout);
    return () => setLogoutHandler(null);
  }, [handleLogout]);

  return null;
}

function App() {
  const [config, setConfig] = useState<{
    logtoEndpoint: string;
    logtoClientId: string;
    logtoResource: string;
  } | null>(null);

  useEffect(() => {
    fetchConfig().then(setConfig);
  }, []);

  if (!config?.logtoClientId) {
    return (
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh' }}>
        <Spinner />
      </div>
    );
  }

  return (
    <LogtoProvider
      config={{
        endpoint: config.logtoEndpoint,
        appId: config.logtoClientId,
        resources: config.logtoResource ? [config.logtoResource] : [],
        scopes: ['openid', 'profile', 'email', 'offline_access'],
      }}
    >
      <TokenSync resource={config.logtoResource} />
      <QueryClientProvider client={queryClient}>
        <BrowserRouter>
          <AppRouter />
        </BrowserRouter>
      </QueryClientProvider>
    </LogtoProvider>
  );
}

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <ThemeProvider>
      <ToastProvider>
        <BreadcrumbProvider>
          <GlobalFilterProvider>
            <App />
          </GlobalFilterProvider>
        </BreadcrumbProvider>
      </ToastProvider>
    </ThemeProvider>
  </React.StrictMode>,
);
