import './global.css';
import './libs/patch-user-card';

import Center from '@arcblock/ux/lib/Center';
import withTracker from '@arcblock/ux/lib/withTracker';
import { ConfigProvider } from '@arcblock/ux/lib/Config';
import { ToastProvider } from '@arcblock/ux/lib/Toast';
import { CircularProgress } from '@mui/material';
import React, { Suspense, useEffect } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { PaymentThemeProvider, usePreventWheel } from '@blocklet/payment-react';
import { Navigate, Route, BrowserRouter as Router, Routes, useNavigate } from 'react-router-dom';
import { joinURL } from 'ufo';

import ErrorFallback from './components/error-fallback';
import UserLayoutDefault from './components/layout/user';
import UserLayoutCF from './components/layout/user-cf';
import { TransitionProvider } from './components/progress-bar';
import { SessionProvider } from './contexts/session';
import { translations } from './locales';

const UserLayout = (window as any).blocklet?.cloudflareWorker ? UserLayoutCF : UserLayoutDefault;

const HomePage = React.lazy(() => import('./pages/home'));
const CheckoutPage = React.lazy(() => import('./pages/checkout'));
const AdminPage = React.lazy(() => import('./pages/admin'));
const CustomerHome = React.lazy(() => import('./pages/customer/index'));
const CustomerInvoiceDetail = React.lazy(() => import('./pages/customer/invoice/detail'));
const CustomerInvoicePastDue = React.lazy(() => import('./pages/customer/invoice/past-due'));
const CustomerSubscriptionDetail = React.lazy(() => import('./pages/customer/subscription/detail'));
const CustomerSubscriptionEmbed = React.lazy(() => import('./pages/customer/subscription/embed'));
const CustomerSubscriptionChangePlan = React.lazy(() => import('./pages/customer/subscription/change-plan'));
const CustomerSubscriptionChangePayment = React.lazy(() => import('./pages/customer/subscription/change-payment'));
const CustomerCreditGrantDetail = React.lazy(() => import('./pages/customer/credit-grant/detail'));
const CustomerCreditTransactionDetail = React.lazy(() => import('./pages/customer/credit-transaction/detail'));
const CustomerRecharge = React.lazy(() => import('./pages/customer/recharge/subscription'));
const CustomerPayoutDetail = React.lazy(() => import('./pages/customer/payout/detail'));
const IntegrationsPage = React.lazy(() => import('./pages/integrations'));
const CustomerBalanceRecharge = React.lazy(() => import('./pages/customer/recharge/account'));

// const theme = createTheme({
//   typography: {
//     fontSize: 14,
//     allVariants: {
//       textTransform: 'none',
//     },
//   },
// });

/**
 * Intercept anchor clicks on internal URLs and do client-side navigation.
 *
 * Some third-party components (e.g. @blocklet/ui-react Dashboard sidebar) render
 * navigation items as `<a href="/admin">` with `external: true`, which triggers
 * a full page reload on click. That reload re-runs session bootstrap and races
 * with page-level auth checks, sometimes redirecting the user back to "/".
 *
 * This handler catches all left-clicks on `<a>` elements with same-origin URLs
 * and converts them into React Router navigation. Modified clicks (cmd/ctrl/shift),
 * target="_blank", and external URLs are left untouched.
 */
function useInternalLinkInterceptor() {
  const navigate = useNavigate();
  useEffect(() => {
    const handler = (e: MouseEvent) => {
      // Only primary button, no modifier keys (so cmd+click still opens in new tab)
      if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
      const anchor = (e.target as HTMLElement | null)?.closest('a');
      if (!anchor) return;
      // Skip if not a real anchor with href
      const href = anchor.getAttribute('href');
      if (!href) return;
      // Skip target="_blank" / download / rel=external
      if (anchor.target && anchor.target !== '' && anchor.target !== '_self') return;
      if (anchor.hasAttribute('download')) return;
      // Skip non-http(s) schemes: mailto:, tel:, javascript:, #hash, etc.
      if (/^[a-z]+:/i.test(href) && !/^https?:/i.test(href)) return;
      if (href.startsWith('#')) return;
      // Resolve to absolute URL and check same-origin
      let url: URL;
      try {
        url = new URL(href, window.location.href);
      } catch {
        return;
      }
      if (url.origin !== window.location.origin) return;
      // Convert to client-side navigation — strip basename prefix so React Router
      // doesn't double it (e.g. /payment/integrations → /integrations when basename="/payment/")
      e.preventDefault();
      const prefix = window?.blocklet?.prefix || '/';
      let navPath = url.pathname + url.search + url.hash;
      if (prefix !== '/' && navPath.startsWith(prefix.replace(/\/$/, ''))) {
        navPath = navPath.slice(prefix.replace(/\/$/, '').length) || '/';
      }
      navigate(navPath);
    };
    document.addEventListener('click', handler);
    return () => document.removeEventListener('click', handler);
  }, [navigate]);
}

function App() {
  useInternalLinkInterceptor();
  return (
    <TransitionProvider>
      <ErrorBoundary FallbackComponent={ErrorFallback} onReset={() => window.location.reload()}>
        <Suspense
          fallback={
            <Center>
              <CircularProgress />
            </Center>
          }>
          <Routes>
            <Route path="/" element={<HomePage />} />
            <Route path="/checkout/:action/:id" element={<CheckoutPage />} />
            <Route key="admin-index" path="/admin" element={<AdminPage />} />,
            <Route key="admin-tabs" path="/admin/:group" element={<AdminPage />} />,
            <Route key="admin-sub" path="/admin/:group/:page" element={<AdminPage />} />,
            <Route key="admin-detail" path="/admin/:group/:page/:id" element={<AdminPage />} />,
            <Route key="admin-nested" path="/admin/:group/:page/:subpage/:id" element={<AdminPage />} />,
            <Route key="admin-fallback" path="/admin/*" element={<AdminPage />} />,
            <Route key="integrations-index" path="/integrations" element={<IntegrationsPage />} />
            <Route key="integrations-tabs" path="/integrations/:group" element={<IntegrationsPage />} />
            <Route key="integrations-sub" path="/integrations/:group/:page" element={<IntegrationsPage />} />
            <Route key="integrations-fallback" path="/integrations/*" element={<IntegrationsPage />} />
            <Route
              key="customer-home"
              path="/customer"
              element={
                <UserLayout>
                  <CustomerHome />
                </UserLayout>
              }
            />
            <Route
              key="customer-subscription"
              path="/customer/subscription/:id"
              element={
                <UserLayout>
                  <CustomerSubscriptionDetail />
                </UserLayout>
              }
            />
            <Route
              key="customer-subscription-change-plan"
              path="/customer/subscription/:id/change-plan"
              element={
                <UserLayout>
                  <CustomerSubscriptionChangePlan />
                </UserLayout>
              }
            />
            <Route
              key="customer-subscription-change-payment"
              path="/customer/subscription/:id/change-payment"
              element={
                <UserLayout>
                  <CustomerSubscriptionChangePayment />
                </UserLayout>
              }
            />
            <Route
              key="customer-recharge"
              path="/customer/subscription/:id/recharge"
              element={
                <UserLayout>
                  <CustomerRecharge />
                </UserLayout>
              }
            />
            <Route
              key="customer-balance-recharge"
              path="/customer/recharge/:currencyId"
              element={
                <UserLayout>
                  <CustomerBalanceRecharge />
                </UserLayout>
              }
            />
            <Route key="customer-embed" path="/customer/embed/subscription" element={<CustomerSubscriptionEmbed />} />
            <Route
              key="subscription-embed"
              path="/embed/customer/subscription"
              element={<CustomerSubscriptionEmbed />}
            />
            <Route
              key="customer-due"
              path="/customer/invoice/past-due"
              element={
                <UserLayout>
                  <CustomerInvoicePastDue />
                </UserLayout>
              }
            />
            <Route
              key="customer-invoice"
              path="/customer/invoice/:id"
              element={
                <UserLayout>
                  <CustomerInvoiceDetail />
                </UserLayout>
              }
            />
            <Route
              key="customer-payout"
              path="/customer/payout/:id"
              element={
                <UserLayout>
                  <CustomerPayoutDetail />
                </UserLayout>
              }
            />
            <Route
              key="customer-credit-grant"
              path="/customer/credit-grant/:id"
              element={
                <UserLayout>
                  <CustomerCreditGrantDetail />
                </UserLayout>
              }
            />
            <Route
              key="customer-credit-transaction"
              path="/customer/credit-transaction/:id"
              element={
                <UserLayout>
                  <CustomerCreditTransactionDetail />
                </UserLayout>
              }
            />
            <Route key="customer-fallback" path="/customer/*" element={<Navigate to="/customer" />} />,
            <Route path="*" element={<Navigate to="/" />} />
          </Routes>
        </Suspense>
      </ErrorBoundary>
    </TransitionProvider>
  );
}

const AppWithTracker = withTracker(App);

export default function WrappedApp() {
  // While the blocklet is deploy to a sub path, this will be work properly.
  const prefix = window?.blocklet?.prefix || '/';

  usePreventWheel();

  return (
    <ConfigProvider translations={translations} fallbackLocale="en">
      <ToastProvider>
        <PaymentThemeProvider>
          <SessionProvider
            serviceHost={prefix}
            useSocket={!(window as any).blocklet?.cloudflareWorker}
            protectedRoutes={['/admin/*', '/customer/*', '/integrations/*'].map((item) => joinURL(prefix, item))}>
            <Router basename={prefix}>
              <AppWithTracker />
            </Router>
          </SessionProvider>
        </PaymentThemeProvider>
      </ToastProvider>
    </ConfigProvider>
  );
}
