import React from 'react';
import { Refine } from '@refinedev/core';
import { notificationProvider, ErrorComponent } from '@refinedev/antd';
import { RefineKbar, RefineKbarProvider } from '@refinedev/kbar';
import routerProvider, {
  NavigateToResource,
  UnsavedChangesNotifier,
} from '@refinedev/react-router-v6';
import { BrowserRouter, Outlet, Route, Routes } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { useMemo } from 'react';
import { Spin } from 'antd';
import { Layout } from 'components/layout';
import { ColorModeContextProvider } from 'components/contexts/color-mode';
import { BusinessContextProvider } from 'components/contexts/business';
import { AgentProvider, ElementInspector } from 'components/agentPanel';
import { authProvider } from 'authProvider';
import '@refinedev/antd/dist/reset.css';
import '@gadmin2n/charts/style.css';
import './styles/antd.css';
import './styles/fc.css';
import './styles/index.css';
import { auditLogProvider } from 'auditLogProvider';
import { gadminCrudProvider as dataProvider } from './helpers/http';
import { useDynamicResources } from 'hooks/useDynamicResources';
import { renderRoutes } from 'config/routeRegistry';

const isDev = import.meta.env.DEV;

// Wrapper component that only renders AgentProvider in development
const DevAgentWrapper: React.FC<{ children: React.ReactNode }> = ({
  children,
}) => {
  if (!isDev) return <>{children}</>;
  return (
    <AgentProvider>
      {children}
      <ElementInspector />
    </AgentProvider>
  );
};

function App() {
  const { i18n } = useTranslation();

  // Stable reference — i18n object identity never changes, so this memo runs once.
  // i18n.t / i18n.language are called at invocation time, always returning fresh values.
  const i18nProvider = useMemo(
    () => ({
      translate: (key: string, defaultMessage?: string) =>
        i18n.t(key, defaultMessage ?? ''),
      changeLocale: (lang: string) => i18n.changeLanguage(lang),
      getLocale: () => i18n.language,
    }),
    [i18n],
  );

  const resources = useDynamicResources();

  return (
    <BrowserRouter basename={isDev ? '/app' : '/'}>
      <RefineKbarProvider>
        <BusinessContextProvider>
          <ColorModeContextProvider>
            <DevAgentWrapper>
              <Refine
                resources={resources}
                notificationProvider={notificationProvider}
                routerProvider={routerProvider}
                i18nProvider={i18nProvider}
                authProvider={authProvider}
                auditLogProvider={auditLogProvider(dataProvider)}
                dataProvider={{
                  default: dataProvider,
                }}
                options={{
                  syncWithLocation: true,
                  warnWhenUnsavedChanges: true,
                  breadcrumb: null,
                }}
              >
                {resources.length === 0 ? (
                  <div
                    style={{
                      display: 'flex',
                      justifyContent: 'center',
                      alignItems: 'center',
                      height: '100vh',
                    }}
                  >
                    <Spin size="large" />
                  </div>
                ) : (
                  <Routes>
                    <Route
                      path="/"
                      element={
                        <Layout>
                          <Outlet />
                        </Layout>
                      }
                    >
                      <Route
                        index
                        element={
                          <NavigateToResource
                            resource={(() => {
                              // Find first leaf resource (has list URL, not used as parent by others)
                              const parentNames = new Set(
                                resources
                                  .map((r) => r.meta?.parent)
                                  .filter(Boolean),
                              );
                              return (
                                resources.find(
                                  (r) => r.list && !parentNames.has(r.name),
                                ) ?? resources.find((r) => r.list)
                              )?.name;
                            })()}
                          />
                        }
                      />
                      {renderRoutes()}
                      <Route path="*" element={<ErrorComponent />} />
                    </Route>
                  </Routes>
                )}
                <RefineKbar />
                <UnsavedChangesNotifier />
              </Refine>
            </DevAgentWrapper>
          </ColorModeContextProvider>
        </BusinessContextProvider>
      </RefineKbarProvider>
    </BrowserRouter>
  );
}

export default App;
