/**
 * Root Application Component
 * Handles routing and global providers
 */
import { Navigate, Routes, Route, useNavigate, useLocation } from 'react-router-dom';
import { Component, useEffect, useState } from 'react';
import type { ErrorInfo, ReactNode } from 'react';
import { Toaster } from 'sonner';
import i18n from './i18n';
import { MainLayout } from './components/layout/MainLayout';
import { TooltipProvider } from '@/components/ui/tooltip';
import { Models } from './pages/Models';
import { Projects } from './pages/Projects';
import { Sessions } from './pages/Sessions';
import { Chat } from './pages/Chat';
import { Home } from './pages/Home';
import { PreviewScene } from './pages/Makelore';
import { ProjectConfiguration } from './pages/ProjectConfiguration';
import { Workbench } from './pages/Workbench';
import { ImageCanvas } from './pages/ImageCanvas';
import { DevicePreview } from './pages/DevicePreview';
import { Settings } from './pages/Settings';
import { Setup } from './pages/Setup';
import { Login } from './pages/Login';
import { ModuleSelection } from './pages/ModuleSelection';
import { useSettingsStore } from './stores/settings';
import { useProviderStore } from './stores/providers';
import { useAuthStore } from './stores/auth';
import { useOpencodeStore } from './stores/opencode';
import { useProjectConfigStore } from './stores/project-config';
import { AI_MODULE_SELECTION_PATH } from './lib/ai-modules';
import { useUserSyncStore } from './stores/user-sync';
import { subscribeHostEvent } from '@/lib/host-events';


/**
 * Error Boundary to catch and display React rendering errors
 */
class ErrorBoundary extends Component<
  { children: ReactNode },
  { hasError: boolean; error: Error | null }
> {
  constructor(props: { children: ReactNode }) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, info: ErrorInfo) {
    console.error('React Error Boundary caught error:', error, info);
  }

  render() {
    if (this.state.hasError) {
      return (
        <div style={{
          padding: '40px',
          color: '#7f1d1d',
          background: '#FFFFFF',
          minHeight: '100vh',
          fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'
        }}>
          <h1 style={{ fontSize: '24px', fontWeight: 600, marginBottom: '16px', letterSpacing: '-0.02em' }}>Something went wrong</h1>
          <pre style={{
            whiteSpace: 'pre-wrap',
            wordBreak: 'break-all',
            background: '#FFFFFF',
            padding: '16px',
            borderRadius: '16px',
            fontSize: '14px',
            color: '#27313f',
            border: '1px solid #dfe3e8',
            boxShadow: '0 12px 32px rgba(35, 43, 56, 0.08)'
          }}>
            {this.state.error?.message}
            {'\n\n'}
            {this.state.error?.stack}
          </pre>
          <button
            onClick={() => { this.setState({ hasError: false, error: null }); window.location.reload(); }}
            style={{
              marginTop: '16px',
              padding: '10px 16px',
              background: 'hsl(var(--brand))',
              color: 'white',
              border: 'none',
              borderRadius: '12px',
              fontWeight: 600,
              cursor: 'pointer'
            }}
          >
            Reload
          </button>
        </div>
      );
    }
    return this.props.children;
  }
}

function StartupScreen() {
  return (
    <div className="flex min-h-screen items-center justify-center bg-background text-sm text-muted-foreground">
      Makelore
    </div>
  );
}

function getReturnPath(location: ReturnType<typeof useLocation>): string {
  return `${location.pathname}${location.search}`;
}

function ProtectedLayout({
  authReady,
  authRequired,
  imageWorkspaceLocalDevelopment,
  setupReady,
}: {
  authReady: boolean;
  authRequired: boolean;
  imageWorkspaceLocalDevelopment: boolean;
  setupReady: boolean;
}) {
  const location = useLocation();
  const authenticated = useAuthStore((state) => state.isAuthenticated());
  const allowsAnonymousImageWorkspace = imageWorkspaceLocalDevelopment
    && (location.pathname === '/'
      || location.pathname === '/image-canvas'
      || location.pathname.startsWith('/image-canvas/'));

  if (!setupReady) {
    return <StartupScreen />;
  }

  if (authRequired && !authReady && !allowsAnonymousImageWorkspace) {
    return <StartupScreen />;
  }

  if (authRequired && !allowsAnonymousImageWorkspace && !authenticated) {
    return (
      <Navigate
        to="/login"
        replace
        state={{ from: getReturnPath(location) }}
      />
    );
  }

  return <MainLayout />;
}

function ProtectedModuleSelection({
  authReady,
  authRequired,
  imageWorkspaceLocalDevelopment,
  setupReady,
}: {
  authReady: boolean;
  authRequired: boolean;
  imageWorkspaceLocalDevelopment: boolean;
  setupReady: boolean;
}) {
  const authenticated = useAuthStore((state) => state.isAuthenticated());

  if (!setupReady) {
    return <StartupScreen />;
  }

  if (authRequired && !authReady && !imageWorkspaceLocalDevelopment) {
    return <StartupScreen />;
  }

  if (authRequired && !imageWorkspaceLocalDevelopment && !authenticated) {
    return <Navigate to="/login" replace state={{ from: AI_MODULE_SELECTION_PATH }} />;
  }

  return <ModuleSelection />;
}

function ProjectChatRoute() {
  const activeProject = useOpencodeStore((state) => state.activeProject);
  const loadProjectList = useOpencodeStore((state) => state.loadProjectList);
  const loadProjectConfig = useProjectConfigStore((state) => state.load);
  const [resolvedProjectKey, setResolvedProjectKey] = useState<string | null | undefined>(undefined);
  const [resolvedRoute, setResolvedRoute] = useState<'chat' | 'config'>('config');
  const projectKey = activeProject?.id ?? null;

  useEffect(() => {
    let cancelled = false;

    void (async () => {
      try {
        await loadProjectList();

        const project = useOpencodeStore.getState().activeProject;
        if (!project) {
          if (!cancelled) {
            setResolvedProjectKey(null);
            setResolvedRoute('config');
          }
          return;
        }

        const configResult = await loadProjectConfig(project.id);
        if (!cancelled) {
          setResolvedProjectKey(project.id);
          setResolvedRoute(configResult.status === 'valid' && Boolean(configResult.config?.initialized) ? 'chat' : 'config');
        }
      } catch {
        if (!cancelled) {
          setResolvedProjectKey(projectKey);
          setResolvedRoute('config');
        }
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [loadProjectConfig, loadProjectList, projectKey]);

  if (resolvedProjectKey === undefined || resolvedProjectKey !== projectKey) {
    return <StartupScreen />;
  }
  if (resolvedRoute === 'config') {
    return <Navigate to="/project-config" replace />;
  }
  return <Chat />;
}

function App() {
  const navigate = useNavigate();
  const location = useLocation();
  const rendererOnlyPreview = typeof __NIANCODE_RENDERER_ONLY__ !== 'undefined'
    && __NIANCODE_RENDERER_ONLY__;
  const skipSetupForE2E = typeof window !== 'undefined'
    && new URLSearchParams(window.location.search).get('e2eSkipSetup') === '1';
  const initSettings = useSettingsStore((state) => state.init);
  const language = useSettingsStore((state) => state.language);
  const setupComplete = useSettingsStore((state) => state.setupComplete);
  const initProviders = useProviderStore((state) => state.init);
  const initAuth = useAuthStore((state) => state.init);
  const authInitialized = useAuthStore((state) => state.initialized);
  const authenticated = useAuthStore((state) => state.isAuthenticated());
  const authAccessToken = useAuthStore((state) => state.accessToken);
  const bootstrapUserSync = useUserSyncStore((state) => state.bootstrap);
  const setupReady = setupComplete || skipSetupForE2E || rendererOnlyPreview;
  const authRequired = !skipSetupForE2E && !rendererOnlyPreview;
  const imageWorkspaceLocalDevelopment = window.electron?.imageWorkspaceLocalDevelopment === true;

  useEffect(() => {
    void initAuth();
  }, [initAuth]);

  useEffect(() => {
    const unsubscribe = subscribeHostEvent('auth:session-changed', (session) => {
      useAuthStore.getState().applyMainSession(session);
    });
    return unsubscribe;
  }, []);

  useEffect(() => {
    if (rendererOnlyPreview || !authInitialized || !authAccessToken) return;

    const recordActivity = (event: Event) => {
      if (!event.isTrusted) return;
      void useAuthStore.getState().markActivity();
    };
    window.addEventListener('pointerdown', recordActivity, { passive: true });
    window.addEventListener('touchstart', recordActivity, { passive: true });
    window.addEventListener('wheel', recordActivity, { passive: true });
    window.addEventListener('keydown', recordActivity);
    window.addEventListener('focus', recordActivity);

    return () => {
      window.removeEventListener('pointerdown', recordActivity);
      window.removeEventListener('touchstart', recordActivity);
      window.removeEventListener('wheel', recordActivity);
      window.removeEventListener('keydown', recordActivity);
      window.removeEventListener('focus', recordActivity);
    };
  }, [authAccessToken, authInitialized, rendererOnlyPreview]);

  useEffect(() => {
    initSettings();
  }, [initSettings]);

  // Sync i18n language with persisted settings on mount
  useEffect(() => {
    if (language && language !== i18n.language) {
      i18n.changeLanguage(language);
    }
  }, [language]);

  // Initialize provider snapshot only after the user can enter the app.
  useEffect(() => {
    if (rendererOnlyPreview) return;
    if (!setupReady) return;
    initProviders();
  }, [initProviders, rendererOnlyPreview, setupReady]);

  useEffect(() => {
    if (rendererOnlyPreview) return;
    if (!setupReady) return;
    if (!authInitialized) return;
    if (!authenticated) return;
    void bootstrapUserSync();
  }, [authenticated, authInitialized, bootstrapUserSync, rendererOnlyPreview, setupReady]);

  // Redirect to setup wizard if not complete
  useEffect(() => {
    if (rendererOnlyPreview && location.pathname.startsWith('/setup')) {
      navigate('/');
      return;
    }

    if (!setupComplete && !skipSetupForE2E && !rendererOnlyPreview && !location.pathname.startsWith('/setup')) {
      navigate('/setup');
    }
  }, [setupComplete, skipSetupForE2E, rendererOnlyPreview, location.pathname, navigate]);

  // Listen for navigation events from main process
  useEffect(() => {
    if (!window.electron?.ipcRenderer?.on) return;

    const handleNavigate = (...args: unknown[]) => {
      const path = args[0];
      if (typeof path === 'string') {
        navigate(path);
      }
    };

    const unsubscribe = window.electron.ipcRenderer.on('navigate', handleNavigate);

    return () => {
      if (typeof unsubscribe === 'function') {
        unsubscribe();
      }
    };
  }, [navigate]);

  // Apply the product palette. Makelore now uses a single light interface.
  useEffect(() => {
    const root = window.document.documentElement;
    root.classList.remove('light', 'dark');
    root.classList.add('light');
  }, []);

  return (
    <ErrorBoundary>
      <TooltipProvider delayDuration={300}>
        <Routes>
          {/* Setup wizard (shown on first launch) */}
          <Route path="/setup/*" element={<Setup />} />
          <Route path="/login" element={<Login />} />
          <Route
            path={AI_MODULE_SELECTION_PATH}
            element={(
              <ProtectedModuleSelection
                authReady={authInitialized}
                authRequired={authRequired}
                imageWorkspaceLocalDevelopment={imageWorkspaceLocalDevelopment}
                setupReady={setupReady}
              />
            )}
          />

          {/* Main application routes */}
          <Route
            element={(
              <ProtectedLayout
                authReady={authInitialized}
                authRequired={authRequired}
                imageWorkspaceLocalDevelopment={imageWorkspaceLocalDevelopment}
                setupReady={setupReady}
              />
            )}
          >
            <Route
              path="/"
              element={<Navigate to={imageWorkspaceLocalDevelopment ? '/image-canvas' : '/opencode-chat'} replace />}
            />
            <Route path="/project-config" element={<ProjectConfiguration />} />
            <Route path="/makelore-home" element={<Home />} />
            <Route path="/kangaroo" element={<Navigate to="/project-config" replace />} />
            <Route path="/subagents" element={<Navigate to="/project-config" replace />} />
            <Route path="/chat" element={<Navigate to="/opencode-chat" replace />} />
            <Route path="/deliverables" element={<PreviewScene />} />
            <Route path="/image-canvas" element={<ImageCanvas />} />
            <Route path="/device-preview" element={<DevicePreview />} />
            <Route path="/workbench/:projectId" element={<Workbench />} />
            <Route path="/opencode-chat" element={<ProjectChatRoute />} />
            <Route path="/projects" element={<Projects />} />
            <Route path="/sessions" element={<Sessions />} />
            <Route path="/models" element={<Models />} />
            <Route path="/settings/*" element={<Settings />} />
            <Route path="*" element={<Navigate to="/" replace />} />
          </Route>
        </Routes>

        {/* Global toast notifications */}
        <Toaster
          position="bottom-right"
          richColors
          closeButton
          style={{ zIndex: 99999 }}
        />
      </TooltipProvider>
    </ErrorBoundary>
  );
}

export default App;
