// src/App.tsx
import React, { useState, useCallback, useEffect } from 'react';
import { Routes, Route, useParams } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import * as pdfjsLib from 'pdfjs-dist';
import { Footer } from './components/Footer';
import { Header } from './components/Header';
import { logger } from './services/logger.client';
import type { Flyer, Profile, UserProfile } from './types';
import { ProfileManager } from './pages/admin/components/ProfileManager';
import { VoiceAssistant } from './features/voice-assistant/VoiceAssistant';
import { AdminPage } from './pages/admin/AdminPage';
import { AdminRoute } from './components/AdminRoute';
import { CorrectionsPage } from './pages/admin/CorrectionsPage';
import { AdminStatsPage } from './pages/admin/AdminStatsPage';
import { ResetPasswordPage } from './pages/ResetPasswordPage';
import { VoiceLabPage } from './pages/VoiceLabPage';
import { FlyerCorrectionTool } from './components/FlyerCorrectionTool';
import { QuestionMarkCircleIcon } from './components/icons/QuestionMarkCircleIcon';
import { useAuth } from './hooks/useAuth';
import { useFlyers } from './hooks/useFlyers';
import { useFlyerItems } from './hooks/useFlyerItems';
import { useModal } from './hooks/useModal';
import { MainLayout } from './layouts/MainLayout';
import config from './config';
import { HomePage } from './pages/HomePage';
import { AppGuard } from './components/AppGuard';
import { useAppInitialization } from './hooks/useAppInitialization';

// pdf.js worker configuration
// This is crucial for allowing pdf.js to process PDFs in a separate thread, preventing the UI from freezing.
// We need to explicitly tell pdf.js where to load its worker script from.
// By importing pdfjs-dist, we can host the worker locally, which is more reliable.
pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
  'pdfjs-dist/build/pdf.worker.mjs',
  import.meta.url,
).toString();

// Create a client
const queryClient = new QueryClient();

function App() {
  const { userProfile, authStatus, login, logout, updateProfile } = useAuth();
  const { flyers } = useFlyers();
  const [selectedFlyer, setSelectedFlyer] = useState<Flyer | null>(null);
  const { openModal, closeModal, isModalOpen } = useModal();
  const params = useParams<{ flyerId?: string }>();

  // This hook now handles initialization effects (OAuth, version check, theme)
  // and returns the theme/unit state needed by other components.
  const { isDarkMode, unitSystem } = useAppInitialization();

  // Debugging: Log renders to identify infinite loops
  useEffect(() => {
    if (process.env.NODE_ENV === 'test') {
      console.log('[App] Render:', {
        flyersCount: flyers.length,
        selectedFlyerId: selectedFlyer?.flyer_id,
        paramsFlyerId: params?.flyerId, // This was a duplicate, fixed.
        authStatus,
        profileId: userProfile?.user.user_id,
      });
    }
  });

  const { flyerItems } = useFlyerItems(selectedFlyer);

  // Define modal handlers with useCallback at the top level to avoid Rules of Hooks violations
  const handleOpenProfile = useCallback(() => openModal('profile'), [openModal]);
  const handleCloseProfile = useCallback(() => closeModal('profile'), [closeModal]);

  const handleOpenVoiceAssistant = useCallback(() => openModal('voiceAssistant'), [openModal]);
  const handleCloseVoiceAssistant = useCallback(() => closeModal('voiceAssistant'), [closeModal]);

  const handleOpenWhatsNew = useCallback(() => openModal('whatsNew'), [openModal]);
  const handleCloseWhatsNew = useCallback(() => closeModal('whatsNew'), [closeModal]);

  const handleOpenCorrectionTool = useCallback(() => openModal('correctionTool'), [openModal]);
  const handleCloseCorrectionTool = useCallback(() => closeModal('correctionTool'), [closeModal]);

  const handleDataExtractedFromCorrection = useCallback(
    (type: 'store_name' | 'dates', value: string) => {
      if (!selectedFlyer) return;

      // This is a simplified update. A real implementation would involve
      // making another API call to update the flyer record in the database.
      // For now, we just update the local state for immediate visual feedback.
      const updatedFlyer = { ...selectedFlyer };
      if (type === 'store_name') {
        updatedFlyer.store = { ...updatedFlyer.store!, name: value };
      } else if (type === 'dates') {
        // A more robust solution would parse the date string properly.
      }
      setSelectedFlyer(updatedFlyer);
    },
    [selectedFlyer],
  );

  const handleProfileUpdate = useCallback(
    (updatedProfileData: Profile) => {
      // When the profile is updated, the API returns a `Profile` object.
      // We need to merge it with the existing `user` object to maintain
      // the `UserProfile` type in our state.
      updateProfile(updatedProfileData);
    },
    [updateProfile],
  );

  // --- State Synchronization and Error Handling ---

  // This is the login handler that will be passed to the ProfileManager component.
  const handleLoginSuccess = useCallback(
    async (userProfile: UserProfile, token: string, _rememberMe: boolean) => {
      try {
        await login(token, userProfile);
        // After successful login, fetch user-specific data
        // The useData hook will automatically refetch user data when `user` changes.
        // We can remove the explicit fetch here.
      } catch (e) {
        // The `login` function within the `useAuth` hook already handles its own errors
        // and notifications, so we just need to log any unexpected failures here.
        logger.error({ err: e }, 'An error occurred during the login success handling.');
      }
    },
    [login],
  );

  const handleFlyerSelect = useCallback(async (flyer: Flyer) => {
    setSelectedFlyer(flyer);
  }, []);

  useEffect(() => {
    if (!selectedFlyer && flyers.length > 0) {
      if (process.env.NODE_ENV === 'test') console.log('[App] Effect: Auto-selecting first flyer');
      handleFlyerSelect(flyers[0]);
    }
  }, [flyers, selectedFlyer, handleFlyerSelect]);

  // New effect to handle routing to a specific flyer ID from the URL
  useEffect(() => {
    const flyerIdFromUrl = params.flyerId;

    if (flyerIdFromUrl && flyers.length > 0) {
      const flyerId = parseInt(flyerIdFromUrl, 10);
      const flyerToSelect = flyers.find((f) => f.flyer_id === flyerId);
      if (flyerToSelect && flyerToSelect.flyer_id !== selectedFlyer?.flyer_id) {
        handleFlyerSelect(flyerToSelect);
      }
    }
  }, [flyers, handleFlyerSelect, selectedFlyer, params.flyerId]);

  // Read the application version injected at build time.
  // This will only be available in the production build, not during local development.
  const appVersion = config.app.version;

  return (
    // AppGuard now handles the main page wrapper, theme styles, and "What's New" modal
    <AppGuard>
      <Header
        isDarkMode={isDarkMode}
        unitSystem={unitSystem}
        userProfile={userProfile}
        authStatus={authStatus}
        onOpenProfile={handleOpenProfile}
        onOpenVoiceAssistant={handleOpenVoiceAssistant}
        onSignOut={logout}
      />

      <ProfileManager
        isOpen={isModalOpen('profile')}
        onClose={handleCloseProfile}
        authStatus={authStatus}
        userProfile={userProfile}
        onProfileUpdate={handleProfileUpdate}
        onLoginSuccess={handleLoginSuccess}
        onSignOut={logout}
      />
      {userProfile && (
        <VoiceAssistant
          isOpen={isModalOpen('voiceAssistant')}
          onClose={handleCloseVoiceAssistant}
        />
      )}

      {selectedFlyer && (
        <FlyerCorrectionTool
          isOpen={isModalOpen('correctionTool')}
          onClose={handleCloseCorrectionTool}
          imageUrl={selectedFlyer.image_url}
          onDataExtracted={handleDataExtractedFromCorrection}
        />
      )}

      <Routes>
        <Route
          element={
            <MainLayout
              onFlyerSelect={handleFlyerSelect}
              selectedFlyerId={selectedFlyer?.flyer_id || null}
              onOpenProfile={handleOpenProfile}
            />
          }
        >
          <Route
            index
            element={
              <HomePage
                selectedFlyer={selectedFlyer}
                flyerItems={flyerItems}
                onOpenCorrectionTool={handleOpenCorrectionTool}
              />
            }
          />
          <Route
            path="/flyers/:flyerId"
            element={
              <HomePage
                selectedFlyer={selectedFlyer}
                flyerItems={flyerItems}
                onOpenCorrectionTool={handleOpenCorrectionTool}
              />
            }
          />
        </Route>

        {/* Admin Routes */}
        <Route element={<AdminRoute profile={userProfile} />}>
          <Route path="/admin" element={<AdminPage />} />
          <Route path="/admin/corrections" element={<CorrectionsPage />} />
          <Route path="/admin/stats" element={<AdminStatsPage />} />
          <Route path="/admin/voice-lab" element={<VoiceLabPage />} />
        </Route>
        <Route path="/reset-password/:token" element={<ResetPasswordPage />} />

        {/* Add other top-level routes here if needed */}
      </Routes>

      {appVersion && (
        <div className="fixed bottom-2 left-3 z-50 flex items-center space-x-2">
          <a
            href={config.app.commitUrl || '#'}
            target="_blank"
            rel="noopener noreferrer"
            title="View commit details on Gitea"
            className="text-xs text-gray-400 dark:text-gray-600 bg-gray-100 dark:bg-gray-950 px-2 py-1 rounded hover:text-brand-primary dark:hover:text-brand-primary transition-colors"
          >
            Version: {appVersion}
          </a>
          <button onClick={handleOpenWhatsNew} title="Show what's new in this version">
            <QuestionMarkCircleIcon className="w-5 h-5 text-gray-400 dark:text-gray-600 hover:text-brand-primary dark:hover:text-brand-primary transition-colors" />
          </button>
        </div>
      )}

      <Footer />
    </AppGuard>
  );
}

const WrappedApp = () => (
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>
);

export default WrappedApp;
