import React, { useEffect } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { Provider as JotaiProvider, useAtomValue } from 'jotai';
import {
  Box,
  Button,
  config,
  OverlayContainerProvider,
  PopOutContainerProvider,
  Text,
  toRem,
  TooltipContainerProvider,
} from 'folds';
import { RouterProvider } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

import { ClientConfigLoader } from '../components/ClientConfigLoader';
import { ClientConfigProvider } from '../hooks/useClientConfig';
import { ConfigConfigError, ConfigConfigLoading } from './ConfigConfig';
import { FeatureCheck } from './FeatureCheck';
import { createRouter } from './Router';
import { ScreenSizeProvider, useScreenSize } from '../hooks/useScreenSize';
import { useCompositionEndTracking } from '../hooks/useComposingCheck';
import { settingsAtom } from '../state/settings';
import { LotusToastContainer } from '../features/toast/LotusToastContainer';
import { useTauriNotificationBadge } from '../hooks/useTauriNotificationBadge';
import { SeasonalEffect } from '../components/seasonal/SeasonalEffect';
import { applyCustomAccent, removeCustomAccent } from '../utils/accentColor';

const FONT_MAP: Record<string, string> = {
  system: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
  inter: "'InterVariable', sans-serif",
  'jetbrains-mono': "'JetBrains Mono', monospace",
  'fira-code': "'Fira Code', monospace",
};

function AppearanceEffects() {
  const settings = useAtomValue(settingsAtom);

  useEffect(() => {
    const color = settings.mentionHighlightColor;
    if (color) {
      document.body.style.setProperty('--mention-highlight-bg', color);
      // WCAG 2.1 relative luminance with gamma linearization
      const toLinear = (c: number) => {
        const s = c / 255;
        return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
      };
      const r = parseInt(color.slice(1, 3), 16);
      const g = parseInt(color.slice(3, 5), 16);
      const b = parseInt(color.slice(5, 7), 16);
      const lum = 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
      document.body.style.setProperty('--mention-highlight-text', lum > 0.179 ? '#000' : '#fff');
      // Derive a visible border: same hue, reduced alpha
      document.body.style.setProperty('--mention-highlight-border', `rgba(${r},${g},${b},0.5)`);
    } else {
      document.body.style.removeProperty('--mention-highlight-bg');
      document.body.style.removeProperty('--mention-highlight-text');
      document.body.style.removeProperty('--mention-highlight-border');
    }
  }, [settings.mentionHighlightColor]);

  useEffect(() => {
    // Custom accent color applies only to non-TDS themes. When Lotus Terminal
    // (TDS) is active it has its own fixed palette, so we remove any overrides.
    const accent = settings.customAccentColor;
    if (accent && !settings.lotusTerminal && applyCustomAccent(accent)) {
      return () => removeCustomAccent();
    }
    removeCustomAccent();
    return undefined;
  }, [settings.customAccentColor, settings.lotusTerminal]);

  useEffect(() => {
    const font = FONT_MAP[settings.fontFamily ?? 'inter'] ?? FONT_MAP.inter;
    document.body.style.setProperty('--font-secondary', font);
  }, [settings.fontFamily]);

  return null;
}

function TauriEffects() {
  useTauriNotificationBadge();
  return null;
}

function NightLightOverlay() {
  const settings = useAtomValue(settingsAtom);
  if (!settings.nightLightEnabled) return null;
  return (
    <div
      aria-hidden="true"
      style={{
        position: 'fixed',
        inset: 0,
        pointerEvents: 'none',
        zIndex: 9998,
        backgroundColor: `rgba(255, 140, 0, ${(settings.nightLightOpacity ?? 30) / 100})`,
      }}
    />
  );
}

const queryClient = new QueryClient();

function App() {
  const screenSize = useScreenSize();
  useCompositionEndTracking();

  const portalContainer = document.getElementById('portalContainer') ?? undefined;

  return (
    <ErrorBoundary
      fallbackRender={({ error, resetErrorBoundary }) => (
        <Box
          direction="Column"
          alignItems="Center"
          justifyContent="Center"
          gap="400"
          style={{ height: '100vh', padding: config.space.S700, textAlign: 'center' }}
        >
          <Text size="H2">Something went wrong</Text>
          <Text size="T300" priority="300" style={{ maxWidth: toRem(400) }}>
            {error instanceof Error ? error.message : 'An unexpected error occurred.'}
          </Text>
          <Button variant="Primary" onClick={resetErrorBoundary}>
            <Text as="span" size="B400">
              Try again
            </Text>
          </Button>
        </Box>
      )}
    >
      <TooltipContainerProvider value={portalContainer}>
        <PopOutContainerProvider value={portalContainer}>
          <OverlayContainerProvider value={portalContainer}>
            <ScreenSizeProvider value={screenSize}>
              <FeatureCheck>
                <ClientConfigLoader
                  fallback={() => <ConfigConfigLoading />}
                  error={(err, retry, ignore) => (
                    <ConfigConfigError error={err} retry={retry} ignore={ignore} />
                  )}
                >
                  {(clientConfig) => (
                    <ClientConfigProvider value={clientConfig}>
                      <QueryClientProvider client={queryClient}>
                        <JotaiProvider>
                          <AppearanceEffects />
                          <TauriEffects />
                          <RouterProvider router={createRouter(clientConfig, screenSize)} />
                          <SeasonalEffect />
                          <NightLightOverlay />
                          <LotusToastContainer />
                        </JotaiProvider>
                        <ReactQueryDevtools initialIsOpen={false} />
                      </QueryClientProvider>
                    </ClientConfigProvider>
                  )}
                </ClientConfigLoader>
              </FeatureCheck>
            </ScreenSizeProvider>
          </OverlayContainerProvider>
        </PopOutContainerProvider>
      </TooltipContainerProvider>
    </ErrorBoundary>
  );
}

export default App;
