import { useState, useEffect, useCallback, useMemo } from 'react';
import MapPage, { type ExportState } from './components/map/MapPage';
import PricingPage from './components/pricing/PricingPage';
import HomePage from './components/home/HomePage';
import LearnPage from './components/learn/LearnPage';
import AccountPage, { SavedPage, InvitesPage } from './components/account/AccountPage';
import InvitePage from './components/invite/InvitePage';
import Header, { type Page } from './components/ui/Header';
import AuthModal from './components/ui/AuthModal';
import SaveSearchModal from './components/ui/SaveSearchModal';
import LicenseSuccessModal from './components/ui/LicenseSuccessModal';
import type { FeatureMeta, FeatureGroup, POICategoriesResponse, POICategoryGroup } from './types';
import { fetchWithRetry, apiUrl } from './lib/api';
import { trackEvent } from './lib/analytics';
import { parseUrlState } from './lib/url-state';
import { INITIAL_VIEW_STATE } from './lib/consts';
import { useTheme } from './hooks/useTheme';
import { useIsMobile } from './hooks/useIsMobile';
import { useAuth } from './hooks/useAuth';
import { useTelemetry } from './hooks/useTelemetry';
import { useSavedSearches } from './hooks/useSavedSearches';
import { useSavedProperties } from './hooks/useSavedProperties';

declare global {
  interface Window {
    __screenshot_ready?: boolean;
  }
}

function pageToPath(page: Page, inviteCode?: string): string {
  switch (page) {
    case 'dashboard':
      return '/dashboard';
    case 'learn':
      return '/learn';
    case 'pricing':
      return '/pricing';
    case 'saved':
      return '/saved';
    case 'invites':
      return '/invites';
    case 'account':
      return '/account';
    case 'invite':
      return `/invite/${inviteCode || ''}`;
    default:
      return '/';
  }
}

function pathToPage(pathname: string): { page: Page; inviteCode?: string } | null {
  if (pathname === '/dashboard') return { page: 'dashboard' };
  if (pathname === '/saved') return { page: 'saved' };
  if (pathname === '/invites') return { page: 'invites' };
  if (pathname === '/learn') return { page: 'learn' };
  if (pathname === '/pricing') return { page: 'pricing' };
  if (pathname === '/account') return { page: 'account' };
  if (pathname === '/support') return { page: 'learn' };
  if (pathname.startsWith('/invite/')) {
    const code = pathname.slice('/invite/'.length);
    return { page: 'invite', inviteCode: code };
  }
  if (pathname === '/') return { page: 'home' };
  return null;
}

export default function App() {
  const urlState = useMemo(() => parseUrlState(), []);
  const initialViewState = useMemo(
    () => urlState.viewState || INITIAL_VIEW_STATE,
    [urlState.viewState]
  );

  const isScreenshotMode = useMemo(() => {
    const params = new URLSearchParams(window.location.search);
    return params.get('screenshot') === '1';
  }, []);
  const isOgMode = useMemo(() => {
    const params = new URLSearchParams(window.location.search);
    return params.get('og') === '1';
  }, []);

  const [features, setFeatures] = useState<FeatureMeta[]>([]);
  const [poiCategoryGroups, setPOICategoryGroups] = useState<POICategoryGroup[]>([]);
  const [initialLoading, setInitialLoading] = useState(true);
  const [pendingInfoFeature, setPendingInfoFeature] = useState<string | null>(null);
  const [inviteCode, setInviteCode] = useState<string | null>(() => {
    const fromPath = pathToPage(window.location.pathname);
    return fromPath?.inviteCode ?? null;
  });
  const [activePage, setActivePage] = useState<Page>(() => {
    if (isScreenshotMode) return 'dashboard';

    // Derive page from URL pathname
    const fromPath = pathToPage(window.location.pathname);
    if (fromPath) return fromPath.page;

    // Restore from history state (e.g. popstate)
    if (window.history.state?.page) return window.history.state.page;

    // Unknown path — track as 404
    if (window.location.pathname !== '/') {
      trackEvent('404', { path: window.location.pathname });
    }
    return 'home';
  });

  const { theme, toggleTheme } = useTheme();
  const isMobile = useIsMobile();
  useTelemetry();
  const {
    user,
    loading: authLoading,
    error: authError,
    login,
    register,
    loginWithOAuth,
    logout,
    requestPasswordReset,
    refreshAuth,
    clearError,
  } = useAuth();
  const [showAuthModal, setShowAuthModal] = useState(false);
  const [authModalTab, setAuthModalTab] = useState<'login' | 'register'>('login');
  const [showLicenseSuccess, setShowLicenseSuccess] = useState(false);
  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    if (params.get('license_success') === '1') {
      params.delete('license_success');
      const newUrl = params.toString()
        ? `${window.location.pathname}?${params.toString()}`
        : window.location.pathname;
      window.history.replaceState({}, '', newUrl);
      trackEvent('Purchase');
      setShowLicenseSuccess(true);
      refreshAuth();
    }
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  const savedSearches = useSavedSearches(user?.id ?? null);
  const savedProperties = useSavedProperties(user?.id ?? null);
  const [showSaveModal, setShowSaveModal] = useState(false);

  useEffect(() => {
    const controller = new AbortController();
    let featuresLoaded = false;
    let poisLoaded = false;

    const checkDone = () => {
      if (featuresLoaded && poisLoaded) setInitialLoading(false);
    };

    fetchWithRetry<{ groups: FeatureGroup[] }>(
      apiUrl('features'),
      (json) => {
        const flat: FeatureMeta[] = json.groups.flatMap((g) =>
          g.features.map((f) => ({ ...f, group: g.name }))
        );
        setFeatures(flat);
        featuresLoaded = true;
        checkDone();
      },
      controller.signal
    );

    fetchWithRetry<POICategoriesResponse>(
      apiUrl('poi-categories'),
      (json) => {
        setPOICategoryGroups(json.groups);
        poisLoaded = true;
        checkDone();
      },
      controller.signal
    );

    return () => controller.abort();
  }, []);

  const navigateTo = useCallback(
    (page: Page, hash?: string, infoFeature?: string) => {
      if (infoFeature) {
        window.history.replaceState({ ...window.history.state, infoFeature }, '');
      }
      const path = pageToPath(page, inviteCode ?? undefined);
      const url = hash ? `${path}#${hash}` : path;
      window.history.pushState({ page }, '', url);
      setActivePage(page);
    },
    [inviteCode]
  );

  useEffect(() => {
    if (!window.history.state?.page) {
      window.history.replaceState(
        { page: activePage },
        '',
        pageToPath(activePage) + window.location.search + window.location.hash
      );
    }
    const handlePopState = (e: PopStateEvent) => {
      if (e.state?.page) {
        setActivePage(e.state.page);
        if (e.state.infoFeature) {
          setPendingInfoFeature(e.state.infoFeature);
        }
      } else {
        // Fall back to deriving page from pathname
        const parsed = pathToPage(window.location.pathname);
        setActivePage(parsed?.page || 'home');
        if (parsed?.inviteCode) setInviteCode(parsed.inviteCode);
      }
    };
    window.addEventListener('popstate', handlePopState);
    return () => window.removeEventListener('popstate', handlePopState);
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  const { fetchSearches } = savedSearches;
  const { fetchProperties: fetchSavedProperties } = savedProperties;
  useEffect(() => {
    if (activePage === 'saved') {
      fetchSearches();
      fetchSavedProperties();
    }
    if (activePage === 'dashboard' && user) {
      fetchSavedProperties();
    }
  }, [activePage, fetchSearches, fetchSavedProperties, user]);

  const isAuthRequiredPage =
    activePage === 'account' || activePage === 'saved' || activePage === 'invites';
  useEffect(() => {
    if (authLoading) return;
    if (isAuthRequiredPage && !user) {
      setAuthModalTab('login');
      setShowAuthModal(true);
      navigateTo('home');
    }
    if (activePage === 'pricing' && (user?.subscription === 'licensed' || user?.isAdmin)) {
      navigateTo('dashboard');
    }
  }, [activePage, isAuthRequiredPage, user, authLoading, navigateTo]);

  const [exportState, setExportState] = useState<ExportState | null>(null);

  if ((isScreenshotMode || isOgMode) && inviteCode) {
    return (
      <InvitePage
        code={inviteCode}
        user={null}
        theme={theme}
        screenshotMode
        onLoginClick={() => {}}
        onRegisterClick={() => {}}
        onLicenseGranted={() => {}}
      />
    );
  }

  if (isScreenshotMode) {
    return (
      <MapPage
        features={features}
        poiCategoryGroups={poiCategoryGroups}
        initialFilters={urlState.filters || { 'Listing status': ['Historical sale'] }}
        initialViewState={initialViewState}
        initialPOICategories={urlState.poiCategories || new Set()}
        initialTab={urlState.tab || 'area'}
        initialLoading={initialLoading}
        theme={theme}
        pendingInfoFeature={null}
        onClearPendingInfoFeature={() => {}}
        onNavigateTo={() => {}}
        screenshotMode
        ogMode={isOgMode}
        initialTravelTime={urlState.travelTime}
      />
    );
  }

  return (
    <div className="h-full flex flex-col">
      <Header
        activePage={activePage}
        onPageChange={navigateTo}
        theme={theme}
        onToggleTheme={toggleTheme}
        onExport={exportState?.onExport ?? null}
        exporting={exportState?.exporting ?? false}
        onSaveSearch={activePage === 'dashboard' && user ? () => setShowSaveModal(true) : null}
        savingSearch={savedSearches.saving}
        user={user}
        onLoginClick={() => {
          setAuthModalTab('login');
          setShowAuthModal(true);
        }}
        onRegisterClick={() => {
          setAuthModalTab('register');
          setShowAuthModal(true);
        }}
        onLogout={logout}
        isMobile={isMobile}
      />
      {activePage === 'home' ? (
        <HomePage
          onOpenDashboard={() => navigateTo('dashboard')}
          onOpenPricing={() => navigateTo('pricing')}
          theme={theme}
          hidePricing={user?.subscription === 'licensed' || user?.isAdmin}
        />
      ) : activePage === 'pricing' && !(user?.subscription === 'licensed' || user?.isAdmin) ? (
        <PricingPage
          onOpenDashboard={() => navigateTo('dashboard')}
          user={user}
          onLoginClick={() => {
            setAuthModalTab('login');
            setShowAuthModal(true);
          }}
          onRegisterClick={() => {
            setAuthModalTab('register');
            setShowAuthModal(true);
          }}
        />
      ) : activePage === 'learn' ? (
        <LearnPage />
      ) : activePage === 'saved' && user ? (
        <SavedPage
          searches={savedSearches.searches}
          searchesLoading={savedSearches.loading}
          onDeleteSearch={savedSearches.deleteSearch}
          onUpdateSearchNotes={savedSearches.updateSearchNotes}
          onUpdateSearchName={savedSearches.updateSearchName}
          onOpenSearch={(params) => {
            window.location.href = `/dashboard?${params}`;
          }}
          savedProperties={savedProperties.properties}
          propertiesLoading={savedProperties.loading}
          onDeleteProperty={savedProperties.deleteProperty}
          onUpdatePropertyNotes={savedProperties.updatePropertyNotes}
          onOpenProperty={(postcode) => {
            window.location.href = `/dashboard?pc=${encodeURIComponent(postcode)}`;
          }}
        />
      ) : activePage === 'invites' && user ? (
        <InvitesPage user={user} />
      ) : activePage === 'account' && user ? (
        <AccountPage user={user} onRefreshAuth={refreshAuth} />
      ) : activePage === 'invite' && inviteCode ? (
        <InvitePage
          code={inviteCode}
          user={user}
          theme={theme}
          onLoginClick={() => {
            setAuthModalTab('login');
            setShowAuthModal(true);
          }}
          onRegisterClick={() => {
            setAuthModalTab('register');
            setShowAuthModal(true);
          }}
          onLicenseGranted={() => {
            setShowLicenseSuccess(true);
            refreshAuth();
          }}
        />
      ) : (
        <MapPage
          features={features}
          poiCategoryGroups={poiCategoryGroups}
          initialFilters={urlState.filters || { 'Listing status': ['Historical sale'] }}
          initialViewState={initialViewState}
          initialPOICategories={urlState.poiCategories || new Set()}
          initialTab={urlState.tab || 'area'}
          initialLoading={initialLoading}
          theme={theme}
          pendingInfoFeature={pendingInfoFeature}
          onClearPendingInfoFeature={() => setPendingInfoFeature(null)}
          onNavigateTo={navigateTo}
          onExportStateChange={setExportState}
          isMobile={isMobile}
          initialTravelTime={urlState.travelTime}
          initialPostcode={urlState.postcode}
          user={user}
          onLoginClick={() => {
            setAuthModalTab('login');
            setShowAuthModal(true);
          }}
          onRegisterClick={() => {
            setAuthModalTab('register');
            setShowAuthModal(true);
          }}
          onSaveProperty={user ? savedProperties.saveProperty : undefined}
          onUnsaveProperty={user ? savedProperties.deleteProperty : undefined}
          isPropertySaved={user ? savedProperties.isPropertySaved : undefined}
          getSavedPropertyId={user ? savedProperties.getSavedPropertyId : undefined}
          deferTutorial={showLicenseSuccess}
        />
      )}
      {showAuthModal && (
        <AuthModal
          onClose={() => setShowAuthModal(false)}
          onLogin={login}
          onRegister={register}
          onOAuthLogin={loginWithOAuth}
          onForgotPassword={requestPasswordReset}
          loading={authLoading}
          error={authError}
          onClearError={clearError}
          initialTab={authModalTab}
        />
      )}
      {showSaveModal && (
        <SaveSearchModal
          onClose={() => setShowSaveModal(false)}
          onSave={savedSearches.saveSearch}
          onViewSearches={() => {
            setShowSaveModal(false);
            navigateTo('saved');
          }}
          saving={savedSearches.saving}
          error={savedSearches.error}
        />
      )}
      {showLicenseSuccess && (
        <LicenseSuccessModal
          onClose={() => {
            setShowLicenseSuccess(false);
            navigateTo('dashboard');
          }}
        />
      )}
    </div>
  );
}
