import React, { useState, useEffect, useCallback } from 'react';
import ReactDOM from 'react-dom/client';
import { LogtoProvider, UserScope, useLogto } from '@logto/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { BrowserRouter } from 'react-router';
import { ThemeProvider, ToastProvider, BreadcrumbProvider, GlobalFilterProvider, CommandPaletteProvider, 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';
import { useOrgStore } from './auth/useOrganization';

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

function TokenSync({ resource }: { resource: string }) {
  const { getAccessToken, isAuthenticated, signOut, fetchUserInfo } = useLogto();
  const { currentOrgId, setCurrentOrg, setOrganizations } = useOrgStore();

  // After auth, resolve user's organizations from Logto
  useEffect(() => {
    if (!isAuthenticated) {
      setOrganizations([]);
      setCurrentOrg(null);
      return;
    }

    fetchUserInfo().then((info) => {
      const orgData = (info as Record<string, unknown>)?.organization_data as
        Array<{ id: string; name: string }> | undefined;
      const orgs = orgData ?? [];
      setOrganizations(orgs.map((o) => ({ id: o.id, name: o.name })));

      // Auto-select if user has exactly one org
      if (orgs.length === 1 && !currentOrgId) {
        setCurrentOrg(orgs[0].id);
      }
    }).catch(() => {
      // fetchUserInfo may fail if token is being refreshed
    });
  }, [isAuthenticated]);

  // Set token provider — org-scoped if org selected, plain otherwise
  useEffect(() => {
    if (isAuthenticated && resource) {
      if (currentOrgId) {
        setTokenProvider(() => getAccessToken(resource, currentOrgId));
      } else {
        setTokenProvider(() => getAccessToken(resource));
      }
    } else {
      setTokenProvider(null);
    }
  }, [isAuthenticated, getAccessToken, resource, currentOrgId]);

  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',
          UserScope.Organizations,
          UserScope.OrganizationRoles,
        ],
      }}
    >
      <TokenSync resource={config.logtoResource} />
      <QueryClientProvider client={queryClient}>
        <BrowserRouter>
          <AppRouter />
        </BrowserRouter>
      </QueryClientProvider>
    </LogtoProvider>
  );
}

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