import MainRouter from './router/Main'
import i18next from 'i18next'
import { I18nextProvider } from 'react-i18next'
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import 'swiper/swiper-bundle.css';
import FaJson from './langs/fa.json'
import AuthRouter from './router/Auth';
import { QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { IApiErrorRepsonse } from './types/error.types';
import { refreshToken } from './pages/auth/service/AuthService';
import ToastContainer from './components/Toast';
import { getRefreshToken, removeRefreshToken, removeToken, setRefreshToken, setToken } from './config/func';

i18next.init({
  interpolation: { escapeValue: false },
  lng: 'fa',
  resources: {
    fa: {
      global: FaJson
    }
  }
})

declare global {
  interface Window {
    isRefreshingToken?: boolean;
  }
}

function App() {
  const queryClient = new QueryClient({
    queryCache: new QueryCache({
      onError: async (error: IApiErrorRepsonse, query) => {
        if (error?.response?.status === 401) {
          try {
            // Use a flag to track if refresh is in progress
            if (window.isRefreshingToken) {
              // Wait for the refresh to complete
              await new Promise(resolve => {
                const checkComplete = setInterval(() => {
                  if (!window.isRefreshingToken) {
                    clearInterval(checkComplete);
                    resolve(true);
                  }
                }, 100);
              });
              return;
            }

            // Set the flag to indicate refresh is in progress
            window.isRefreshingToken = true;

            try {
              const refreshTokenValue = await getRefreshToken();
              const { data } = await refreshToken({ refreshToken: refreshTokenValue || '' });

              if (data?.accessToken?.token) {
                // Save the new token
                await setToken(data?.accessToken?.token);

                // If refresh token also returned, update it
                if (data.refreshToken?.token) {
                  await setRefreshToken(data.refreshToken?.token);
                }

                // Retry the failed request, even if it was muted
                if (query) {
                  queryClient.invalidateQueries({ queryKey: query.queryKey });
                } else {
                  queryClient.invalidateQueries();
                }
                return;
              } else {
                throw new Error('Invalid token response');
              }
            } finally {
              window.isRefreshingToken = false;
            }
          } catch (refreshError: unknown) {
            console.error('Token refresh failed:', refreshError);
            // Clear tokens and redirect to login
            await removeToken();
            await removeRefreshToken();
            window.location.href = '/auth/login';
          }
        }
      }
    }),
    defaultOptions: {
      queries: {
        refetchOnWindowFocus: false,
        retry: false
      }
    }
  });

  return (
    <>
      <BrowserRouter>
        <QueryClientProvider client={queryClient}>
          <I18nextProvider i18n={i18next}>
            <Routes>
              <Route path="/:slug/auth/*" element={<AuthRouter />} />
              <Route path="/:slug/*" element={<MainRouter />} />
            </Routes>
            <ToastContainer />
          </I18nextProvider>
        </QueryClientProvider>
      </BrowserRouter>
    </>
  )
}

export default App
