import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import Timeline from '../components/Timeline';
import TimelineEventGuides from '../components/TimelineEventGuides';
import MovementBands from '../components/MovementBands';
import VirtualGallery from '../components/VirtualGallery';
import PaintingDetailView from '../components/PaintingDetail';
import ArtistBio from '../components/ArtistBio';
import CheckupPage from '../pages/CheckupPage';
import TranslationsPage from '../pages/TranslationsPage';
import InfluencesPage from '../pages/InfluencesPage';
import ToursPage from '../pages/ToursPage';
import CuratorLoginModal from '../components/CuratorLoginModal';
import ToursPopup from '../components/ToursPopup';
import CatalogSearchBar from '../components/CatalogSearchBar';
import LocaleSwitcher from '../components/LocaleSwitcher';
import GalleryLoadingMarker from '../components/GalleryLoadingMarker';
import '../components/CatalogSearchBar.css';
import '../components/CuratorLoginModal.css';
import '../components/ToursPopup.css';
import '../components/LocaleSwitcher.css';
import '../pages/TranslationsPage.css';
import '../pages/InfluencesPage.css';
import '../pages/ToursPage.css';
import { useAuth } from '../context/AuthContext';
import { api, setApiLocale, type FixPaintingImageResult, type FixArtistPortraitResult } from '../api/client';
import type {
  TimelineData,
  Artist,
  ArtistDetail,
  Painting,
  PaintingDetail,
  MovementGalleryDetail,
  TourGalleryDetail,
} from '../types';
import { createViewChangeScheduler } from '../utils/timelineView';
import { sortArtistPaintingsChronological } from '../utils/paintingUtils';
import { readDebugMode, readDebugShowMore, writeDebugMode, writeDebugShowMore } from '../utils/debugMode';
import './HomePage.css';

type View =
  | { type: 'timeline' }
  | { type: 'checkup' }
  | { type: 'translations' }
  | { type: 'influences' }
  | { type: 'tours' }
  | { type: 'gallery'; artistId: number; data: ArtistDetail }
  | { type: 'movement-gallery'; movementId: number; data: MovementGalleryDetail }
  | { type: 'tour-gallery'; tourId: number; data: TourGalleryDetail }
  | { type: 'painting'; paintingId: number; data: PaintingDetail; returnTo: View }
  | { type: 'bio'; artistId: number; data: ArtistDetail; returnTo: View };

type GallerySession =
  | { kind: 'artist'; artistId: number; data: ArtistDetail }
  | { kind: 'movement'; movementId: number; data: MovementGalleryDetail }
  | { kind: 'tour'; tourId: number; data: TourGalleryDetail };

type CuratorLoginRedirect = 'checkup' | 'translations' | 'influences' | 'tours' | null;

function patchPaintingInMovementDetail(
  detail: MovementGalleryDetail,
  paintingId: number,
  patch: Partial<Painting>
): MovementGalleryDetail {
  return {
    ...detail,
    paintings: detail.paintings.map((p) => (p.id === paintingId ? { ...p, ...patch } : p)),
  };
}

function patchPaintingInTourDetail(
  detail: TourGalleryDetail,
  paintingId: number,
  patch: Partial<Painting>
): TourGalleryDetail {
  return {
    ...detail,
    paintings: detail.paintings.map((p) => (p.id === paintingId ? { ...p, ...patch } : p)),
  };
}

function patchPaintingInArtistDetail(
  detail: ArtistDetail,
  paintingId: number,
  patch: Partial<Painting>
): ArtistDetail {
  return {
    ...detail,
    paintings: detail.paintings.map((p) => (p.id === paintingId ? { ...p, ...patch } : p)),
  };
}

function patchArtistInArtistDetail(detail: ArtistDetail, patch: Partial<Artist>): ArtistDetail {
  return {
    ...detail,
    artist: { ...detail.artist, ...patch },
  };
}

function patchReturnToAfterRemove(
  returnTo: View,
  freshArtist?: ArtistDetail,
  freshMovement?: MovementGalleryDetail,
  freshTour?: TourGalleryDetail
): View {
  if (returnTo.type === 'gallery' && freshArtist && returnTo.artistId === freshArtist.artist.id) {
    return { ...returnTo, data: freshArtist };
  }
  if (
    returnTo.type === 'movement-gallery' &&
    freshMovement &&
    returnTo.movementId === freshMovement.movement.id
  ) {
    return { ...returnTo, data: freshMovement };
  }
  if (returnTo.type === 'tour-gallery' && freshTour && returnTo.tourId === freshTour.tour.id) {
    return { ...returnTo, data: freshTour };
  }
  if (returnTo.type === 'painting') {
    return {
      ...returnTo,
      returnTo: patchReturnToAfterRemove(returnTo.returnTo, freshArtist, freshMovement, freshTour),
    };
  }
  if (returnTo.type === 'bio') {
    const data =
      freshArtist && returnTo.artistId === freshArtist.artist.id ? freshArtist : returnTo.data;
    return {
      ...returnTo,
      data,
      returnTo: patchReturnToAfterRemove(returnTo.returnTo, freshArtist, freshMovement, freshTour),
    };
  }
  return returnTo;
}

function catalogNavigateTarget(
  sorted: Painting[],
  removedId: number
): number | null {
  const idx = sorted.findIndex((p) => p.id === removedId);
  if (idx < 0) return null;
  const remaining = sorted.filter((p) => p.id !== removedId);
  if (remaining.length === 0) return null;
  return idx < remaining.length ? remaining[idx].id : remaining[remaining.length - 1].id;
}

export default function HomePage() {
  const { t } = useTranslation('home');
  const { isCurator, username, login, logout } = useAuth();
  const [view, setView] = useState<View>({ type: 'timeline' });
  const [gallerySession, setGallerySession] = useState<GallerySession | null>(null);
  const [bounds, setBounds] = useState({ min: -800, max: 2025 });
  const [viewStart, setViewStart] = useState(-800);
  const [viewEnd, setViewEnd] = useState(2025);
  const [timelineData, setTimelineData] = useState<TimelineData>({ eras: [], movements: [] });
  const [artists, setArtists] = useState<Artist[]>([]);
  const [loading, setLoading] = useState(true);
  const [portraitsLoading, setPortraitsLoading] = useState(false);
  const [galleryEntryLoading, setGalleryEntryLoading] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [detailArtistPaintings, setDetailArtistPaintings] = useState<Painting[]>([]);
  const [imageRevisions, setImageRevisions] = useState<Record<number, number>>({});
  const [portraitRevisions, setPortraitRevisions] = useState<Record<number, number>>({});
  const [localeVersion, setLocaleVersion] = useState(0);
  const [debugMode, setDebugMode] = useState(readDebugMode);
  const [debugShowMore, setDebugShowMore] = useState(readDebugShowMore);
  const [loginOpen, setLoginOpen] = useState(false);
  const [loginRedirect, setLoginRedirect] = useState<CuratorLoginRedirect>(null);
  const [toursPopupOpen, setToursPopupOpen] = useState(false);
  const effectiveDebugMode = debugMode && isCurator;
  const [galleryRevision, setGalleryRevision] = useState(0);
  const viewRef = useRef(view);
  viewRef.current = view;
  const [hoveredLifespan, setHoveredLifespan] = useState<{
    birthYear: number;
    deathYear: number;
    color: string;
  } | null>(null);
  const detailReturnToRef = useRef<View>({ type: 'timeline' });

  useEffect(() => {
    if (view.type === 'gallery') {
      setGallerySession({ kind: 'artist', artistId: view.artistId, data: view.data });
    } else if (view.type === 'movement-gallery') {
      setGallerySession({ kind: 'movement', movementId: view.movementId, data: view.data });
    } else if (view.type === 'tour-gallery') {
      setGallerySession({ kind: 'tour', tourId: view.tourId, data: view.data });
    } else if (view.type === 'timeline') {
      setGallerySession(null);
    }
  }, [view]);

  // Load full catalog once — pan/zoom filters client-side (MovementBands, Timeline).
  useEffect(() => {
    let cancelled = false;

    (async () => {
      try {
        setLoading(true);
        const catalog = await api.getCatalogBootstrap();
        if (cancelled) return;

        const min = catalog.bounds.min_year ?? -800;
        const max = catalog.bounds.max_year ?? 2025;
        setBounds({ min, max });
        setViewStart(min);
        setViewEnd(max);
        setTimelineData({ eras: catalog.eras, movements: catalog.movements });
        setArtists(catalog.artists);
        setError(null);
      } catch {
        if (!cancelled) setError('Could not load gallery data. Is the server running?');
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [localeVersion]);

  const handleLocaleChange = useCallback((locale: 'en' | 'ru') => {
    setApiLocale(locale);
    setLocaleVersion((v) => v + 1);
  }, []);

  const viewChangeScheduler = useRef(
    createViewChangeScheduler((start, end) => {
      setViewStart(start);
      setViewEnd(end);
    })
  );

  useEffect(() => () => viewChangeScheduler.current.cancel(), []);

  const handleViewChange = useCallback((start: number, end: number) => {
    viewChangeScheduler.current.schedule(start, end);
  }, []);

  const goToTimelineHome = useCallback(() => {
    detailReturnToRef.current = { type: 'timeline' };
    setGallerySession(null);
    setHoveredLifespan(null);
    setGalleryEntryLoading(null);
    setViewStart(bounds.min);
    setViewEnd(bounds.max);
    setGalleryRevision((revision) => revision + 1);
    setView({ type: 'timeline' });
  }, [bounds.min, bounds.max]);

  const toggleDebugMode = () => {
    setDebugMode((prev) => {
      const next = !prev;
      writeDebugMode(next);
      return next;
    });
  };

  const setDebugShowMoreEnabled = (enabled: boolean) => {
    setDebugShowMore(enabled);
    writeDebugShowMore(enabled);
  };

  const openCuratorLogin = (redirect: CuratorLoginRedirect = null) => {
    setLoginRedirect(redirect);
    setLoginOpen(true);
  };

  const handleCuratorLogin = async (user: string, password: string) => {
    await login(user, password);
    setLoginOpen(false);
    if (loginRedirect === 'checkup') {
      setView({ type: 'checkup' });
    } else if (loginRedirect === 'translations') {
      setView({ type: 'translations' });
    } else if (loginRedirect === 'influences') {
      setView({ type: 'influences' });
    } else if (loginRedirect === 'tours') {
      setView({ type: 'tours' });
    }
    setLoginRedirect(null);
  };

  const handleCuratorLogout = async () => {
    await logout();
    writeDebugMode(false);
    setDebugMode(false);
    if (
      view.type === 'checkup' ||
      view.type === 'translations' ||
      view.type === 'influences' ||
      view.type === 'tours'
    ) {
      goToTimelineHome();
    }
  };

  const openCheckup = () => {
    if (!isCurator) {
      openCuratorLogin('checkup');
      return;
    }
    setView({ type: 'checkup' });
  };

  const openTranslations = () => {
    if (!isCurator) {
      openCuratorLogin('translations');
      return;
    }
    setView({ type: 'translations' });
  };

  const openInfluences = () => {
    if (!isCurator) {
      openCuratorLogin('influences');
      return;
    }
    setView({ type: 'influences' });
  };

  const openToursEditor = () => {
    if (!isCurator) {
      openCuratorLogin('tours');
      return;
    }
    setView({ type: 'tours' });
  };

  const handlePaintingImageFixed = useCallback(async (paintingId: number, fixResult: FixPaintingImageResult) => {
    const data = await api.getPainting(paintingId);
    const patch: Partial<Painting> = {
      image_path: fixResult.imagePath,
      thumbnail_path: fixResult.thumbnailPath,
      image_cache_key: fixResult.image_cache_key ?? null,
      thumbnail_cache_key: fixResult.thumbnail_cache_key ?? null,
      checkup_checked: fixResult.checked ?? true,
      checkup_fixed: fixResult.fixed ?? true,
    };
    const updatedData: PaintingDetail = {
      ...data,
      painting: { ...data.painting, ...patch },
    };

    setImageRevisions((prev) => ({ ...prev, [paintingId]: (prev[paintingId] ?? 0) + 1 }));

    setView((current) => {
      if (current.type !== 'painting' || current.paintingId !== paintingId) return current;
      let returnTo = current.returnTo;
      if (returnTo.type === 'gallery' && returnTo.artistId === data.painting.artist_id) {
        returnTo = {
          ...returnTo,
          data: patchPaintingInArtistDetail(returnTo.data, paintingId, patch),
        };
      }
      if (returnTo.type === 'movement-gallery') {
        returnTo = {
          ...returnTo,
          data: patchPaintingInMovementDetail(returnTo.data, paintingId, patch),
        };
      }
      if (returnTo.type === 'tour-gallery') {
        returnTo = {
          ...returnTo,
          data: patchPaintingInTourDetail(returnTo.data, paintingId, patch),
        };
      }
      return { ...current, data: updatedData, returnTo };
    });

    setDetailArtistPaintings((list) =>
      list.map((p) => (p.id === paintingId ? { ...p, ...patch } : p))
    );

    setGallerySession((session) => {
      if (session?.kind === 'artist' && session.artistId === data.painting.artist_id) {
        return { ...session, data: patchPaintingInArtistDetail(session.data, paintingId, patch) };
      }
      if (session?.kind === 'movement') {
        return { ...session, data: patchPaintingInMovementDetail(session.data, paintingId, patch) };
      }
      if (session?.kind === 'tour') {
        return { ...session, data: patchPaintingInTourDetail(session.data, paintingId, patch) };
      }
      return session;
    });
  }, []);

  const handlePaintingCheckupFlagsUpdated = useCallback(
    async (paintingId: number, flags: { checked: boolean; fixed: boolean }) => {
      const data = await api.getPainting(paintingId);
      const patch: Partial<Painting> = {
        checkup_checked: flags.checked,
        checkup_fixed: flags.fixed,
      };
      const updatedData: PaintingDetail = {
        ...data,
        painting: { ...data.painting, ...patch },
      };

      setView((current) => {
        if (current.type !== 'painting' || current.paintingId !== paintingId) return current;
        let returnTo = current.returnTo;
        if (returnTo.type === 'gallery' && returnTo.artistId === data.painting.artist_id) {
          returnTo = {
            ...returnTo,
            data: patchPaintingInArtistDetail(returnTo.data, paintingId, patch),
          };
        }
        if (returnTo.type === 'movement-gallery') {
          returnTo = {
            ...returnTo,
            data: patchPaintingInMovementDetail(returnTo.data, paintingId, patch),
          };
        }
        if (returnTo.type === 'tour-gallery') {
          returnTo = {
            ...returnTo,
            data: patchPaintingInTourDetail(returnTo.data, paintingId, patch),
          };
        }
        return { ...current, data: updatedData, returnTo };
      });

      setDetailArtistPaintings((list) =>
        list.map((p) => (p.id === paintingId ? { ...p, ...patch } : p))
      );

      setGallerySession((session) => {
        if (session?.kind === 'artist' && session.artistId === data.painting.artist_id) {
          return { ...session, data: patchPaintingInArtistDetail(session.data, paintingId, patch) };
        }
        if (session?.kind === 'movement') {
          return { ...session, data: patchPaintingInMovementDetail(session.data, paintingId, patch) };
        }
        if (session?.kind === 'tour') {
          return { ...session, data: patchPaintingInTourDetail(session.data, paintingId, patch) };
        }
        return session;
      });
    },
    []
  );

  const applyArtistPatch = useCallback((artistId: number, patch: Partial<Artist>) => {
    setArtists((list) => list.map((a) => (a.id === artistId ? { ...a, ...patch } : a)));

    setView((current) => {
      if (current.type === 'bio' && current.artistId === artistId) {
        return { ...current, data: patchArtistInArtistDetail(current.data, patch) };
      }
      if (current.type === 'gallery' && current.artistId === artistId) {
        return { ...current, data: patchArtistInArtistDetail(current.data, patch) };
      }
      if (current.type === 'painting' && current.data.painting.artist_id === artistId) {
        return {
          ...current,
          data: {
            ...current.data,
            painting: {
              ...current.data.painting,
              artist_portrait: patch.portrait_path ?? current.data.painting.artist_portrait,
            },
          },
        };
      }
      return current;
    });

    setGallerySession((session) =>
      session?.kind === 'artist' && session.artistId === artistId
        ? { ...session, data: patchArtistInArtistDetail(session.data, patch) }
        : session
    );
  }, []);

  const handleArtistPortraitFixed = useCallback(
    async (artistId: number, fixResult: FixArtistPortraitResult) => {
      const data = await api.getArtist(artistId);
      const patch: Partial<Artist> = {
        portrait_path: fixResult.portraitPath,
        portrait_thumb_path: fixResult.portraitThumbPath ?? null,
        portrait_cache_key: fixResult.portrait_cache_key ?? null,
        portrait_thumb_cache_key: fixResult.portrait_thumb_cache_key ?? null,
        checkup_checked: fixResult.checked ?? true,
        checkup_fixed: fixResult.fixed ?? true,
      };
      setPortraitRevisions((prev) => ({ ...prev, [artistId]: (prev[artistId] ?? 0) + 1 }));
      applyArtistPatch(artistId, patch);
      setView((current) =>
        current.type === 'bio' && current.artistId === artistId
          ? { ...current, data: { ...data, artist: { ...data.artist, ...patch } } }
          : current
      );
    },
    [applyArtistPatch]
  );

  const handleArtistCheckupFlagsUpdated = useCallback(
    async (artistId: number, flags: { checked: boolean; fixed: boolean }) => {
      const patch: Partial<Artist> = {
        checkup_checked: flags.checked,
        checkup_fixed: flags.fixed,
      };
      applyArtistPatch(artistId, patch);
      setView((current) =>
        current.type === 'bio' && current.artistId === artistId
          ? { ...current, data: patchArtistInArtistDetail(current.data, patch) }
          : current
      );
    },
    [applyArtistPatch]
  );

  const openArtistGallery = useCallback((artistId: number, data: ArtistDetail) => {
    const session: GallerySession = { kind: 'artist', artistId, data };
    setGallerySession(session);
    setView({ type: 'gallery', artistId, data });
  }, []);

  const openMovementGallery = useCallback((movementId: number, data: MovementGalleryDetail) => {
    const session: GallerySession = { kind: 'movement', movementId, data };
    setGallerySession(session);
    setView({ type: 'movement-gallery', movementId, data });
  }, []);

  const openTourGallery = useCallback((tourId: number, data: TourGalleryDetail) => {
    const session: GallerySession = { kind: 'tour', tourId, data };
    setGallerySession(session);
    setView({ type: 'tour-gallery', tourId, data });
  }, []);

  const handleSelectPublishedTour = useCallback(
    async (tourId: number) => {
      setToursPopupOpen(false);
      setGalleryEntryLoading(t('openingTourGallery'));
      try {
        const data = await api.getTour(tourId);
        if (!data.paintings.length) {
          setError(t('tourEmpty'));
          return;
        }
        openTourGallery(tourId, data);
      } catch {
        setError(t('tourLoadFailed'));
      } finally {
        setGalleryEntryLoading(null);
      }
    },
    [openTourGallery, t]
  );

  const handleArtistClick = async (artistId: number) => {
    setGalleryEntryLoading('Opening artist gallery…');
    try {
      await api.preloadArtistImages(artistId).catch(() => undefined);
      const data = await api.getArtist(artistId);
      openArtistGallery(artistId, data);
    } catch {
      setError('Failed to load artist gallery.');
    } finally {
      setGalleryEntryLoading(null);
    }
  };

  const handleMovementClick = async (movementId: number) => {
    setGalleryEntryLoading('Opening movement gallery…');
    try {
      const data = await api.getMovementGallery(movementId);
      openMovementGallery(movementId, data);
    } catch {
      setError('Failed to load movement gallery.');
    } finally {
      setGalleryEntryLoading(null);
    }
  };

  const handlePaintingClick = async (paintingId: number) => {
    try {
      const data = await api.getPainting(paintingId);
      setView((prev) => {
        detailReturnToRef.current = prev;
        return {
          type: 'painting',
          paintingId,
          data,
          returnTo: prev,
        };
      });
    } catch {
      setError('Failed to load painting details.');
    }
  };

  const handleCatalogNavigate = useCallback(async (paintingId: number) => {
    const returnTo = detailReturnToRef.current;
    try {
      const data = await api.getPainting(paintingId);
      setView({
        type: 'painting',
        paintingId,
        data,
        returnTo,
      });
    } catch {
      setError('Failed to load painting details.');
    }
  }, []);

  const handlePaintingRemoved = useCallback(
    async (paintingId: number, artistId: number) => {
      const currentView = viewRef.current;
      if (currentView.type !== 'painting' || currentView.paintingId !== paintingId) return;

      const sorted =
        gallerySession?.kind === 'tour' || currentView.returnTo.type === 'tour-gallery'
          ? detailArtistPaintings
          : sortArtistPaintingsChronological(detailArtistPaintings);
      const nextId = catalogNavigateTarget(sorted, paintingId);
      const inMovementCatalog =
        gallerySession?.kind === 'movement' || currentView.returnTo.type === 'movement-gallery';
      const inTourCatalog =
        gallerySession?.kind === 'tour' || currentView.returnTo.type === 'tour-gallery';

      await api.deletePainting(paintingId);

      const freshArtist = await api.getArtist(artistId);
        let freshMovement: MovementGalleryDetail | undefined;
        let freshTour: TourGalleryDetail | undefined;
        if (gallerySession?.kind === 'movement') {
          freshMovement = await api.getMovementGallery(gallerySession.movementId);
        } else if (currentView.returnTo.type === 'movement-gallery') {
          freshMovement = await api.getMovementGallery(currentView.returnTo.movementId);
        }
        if (gallerySession?.kind === 'tour') {
          freshTour = await api.getTour(gallerySession.tourId);
        } else if (currentView.returnTo.type === 'tour-gallery') {
          freshTour = await api.getTour(currentView.returnTo.tourId);
        }

        const freshCatalog =
          inTourCatalog && freshTour
            ? freshTour.paintings
            : inMovementCatalog && freshMovement
              ? sortArtistPaintingsChronological(freshMovement.paintings)
              : sortArtistPaintingsChronological(freshArtist.paintings);

        const removedIdx = sorted.findIndex((p) => p.id === paintingId);
        const navigateId =
          nextId && freshCatalog.some((p) => p.id === nextId)
            ? nextId
            : freshCatalog.length > 0
              ? freshCatalog[Math.min(removedIdx, freshCatalog.length - 1)]?.id ??
                freshCatalog[0].id
              : null;

        setDetailArtistPaintings(freshCatalog);

        setGallerySession((session) => {
          if (!session) return session;
          if (session.kind === 'artist' && session.artistId === artistId) {
            return { ...session, data: freshArtist };
          }
          if (session.kind === 'movement' && freshMovement) {
            return { ...session, data: freshMovement };
          }
          if (session.kind === 'tour' && freshTour) {
            return { ...session, data: freshTour };
          }
          return session;
        });

        setImageRevisions((prev) => {
          const next = { ...prev };
          delete next[paintingId];
          return next;
        });

        setGalleryRevision((v) => v + 1);

        const patchedReturnTo = patchReturnToAfterRemove(
          currentView.returnTo,
          freshArtist,
          freshMovement,
          freshTour
        );
        detailReturnToRef.current = patchedReturnTo;

        setView((current) => {
          if (current.type === 'gallery' && current.artistId === artistId) {
            return { ...current, data: freshArtist };
          }
          if (current.type === 'movement-gallery' && freshMovement) {
            return { ...current, data: freshMovement };
          }
          if (current.type === 'tour-gallery' && freshTour) {
            return { ...current, data: freshTour };
          }
          if (current.type !== 'painting' || current.paintingId !== paintingId) {
            return current;
          }
          if (navigateId) return current;
          return patchedReturnTo;
        });

        if (navigateId) {
          const data = await api.getPainting(navigateId);
        setView({
          type: 'painting',
          paintingId: navigateId,
          data,
          returnTo: patchedReturnTo,
        });
      }
    },
    [detailArtistPaintings, gallerySession]
  );

  const handleBioClick = (artistData: ArtistDetail, returnTo: View) => {
    setView({ type: 'bio', artistId: artistData.artist.id, data: artistData, returnTo });
  };

  useEffect(() => {
    if (view.type !== 'painting') {
      setDetailArtistPaintings([]);
      return;
    }

    const artistId = view.data.painting.artist_id;
    if (gallerySession?.kind === 'tour') {
      setDetailArtistPaintings(gallerySession.data.paintings);
      return;
    }
    if (gallerySession?.kind === 'artist' && gallerySession.artistId === artistId) {
      setDetailArtistPaintings(gallerySession.data.paintings);
      return;
    }

    const returnTo = detailReturnToRef.current;
    if (returnTo.type === 'tour-gallery') {
      setDetailArtistPaintings(returnTo.data.paintings);
      return;
    }
    if (returnTo.type === 'movement-gallery') {
      setDetailArtistPaintings(sortArtistPaintingsChronological(returnTo.data.paintings));
      return;
    }

    let cancelled = false;
    api.getArtist(artistId)
      .then((data) => {
        if (!cancelled) setDetailArtistPaintings(data.paintings);
      })
      .catch(() => {
        if (!cancelled) setDetailArtistPaintings([]);
      });

    return () => {
      cancelled = true;
    };
  }, [view, gallerySession]);

  const sortedDetailArtistPaintings = useMemo(() => {
    const fromTourSession = gallerySession?.kind === 'tour';
    const fromTourReturn =
      view.type === 'painting' && view.returnTo.type === 'tour-gallery';
    if (fromTourSession || fromTourReturn) {
      return detailArtistPaintings;
    }
    return sortArtistPaintingsChronological(detailArtistPaintings);
  }, [detailArtistPaintings, gallerySession, view]);

  const tourOverlay =
    view.type === 'painting' && gallerySession?.kind === 'tour'
      ? {
          title: gallerySession.data.tour.title,
          text: gallerySession.data.stopBodies[view.paintingId] ?? '',
        }
      : view.type === 'painting' && view.returnTo.type === 'tour-gallery'
        ? {
            title: view.returnTo.data.tour.title,
            text: view.returnTo.data.stopBodies[view.paintingId] ?? '',
          }
        : null;

  const galleryActive =
    view.type === 'gallery' || view.type === 'movement-gallery' || view.type === 'tour-gallery';

  const displayGallery = useMemo((): GallerySession | null => {
    if (view.type === 'gallery') {
      return { kind: 'artist', artistId: view.artistId, data: view.data };
    }
    if (view.type === 'movement-gallery') {
      return { kind: 'movement', movementId: view.movementId, data: view.data };
    }
    if (view.type === 'tour-gallery') {
      return { kind: 'tour', tourId: view.tourId, data: view.data };
    }
    return gallerySession;
  }, [view, gallerySession]);

  return (
    <>
      {displayGallery && (
        <div
          className={galleryActive ? 'gallery-session-active' : 'gallery-session-suspended'}
          aria-hidden={!galleryActive}
        >
          {displayGallery.kind === 'artist' ? (
            <VirtualGallery
              key={`artist-${displayGallery.artistId}-${galleryRevision}`}
              mode="artist"
              data={displayGallery.data}
              imageRevisions={imageRevisions}
              active={galleryActive}
              onPaintingClick={handlePaintingClick}
              onNavigateArtist={handleArtistClick}
              onBack={goToTimelineHome}
              onBioClick={() =>
                handleBioClick(displayGallery.data, {
                  type: 'gallery',
                  artistId: displayGallery.artistId,
                  data: displayGallery.data,
                })
              }
            />
          ) : displayGallery.kind === 'movement' ? (
            <VirtualGallery
              key={`movement-${displayGallery.movementId}-${galleryRevision}`}
              mode="movement"
              data={displayGallery.data}
              imageRevisions={imageRevisions}
              active={galleryActive}
              onPaintingClick={handlePaintingClick}
              onBack={goToTimelineHome}
            />
          ) : (
            <VirtualGallery
              key={`tour-${displayGallery.tourId}-${galleryRevision}`}
              mode="tour"
              data={displayGallery.data}
              imageRevisions={imageRevisions}
              active={galleryActive}
              onPaintingClick={handlePaintingClick}
              onBack={goToTimelineHome}
            />
          )}
        </div>
      )}

      {view.type === 'painting' && (
        <div className="home-overlay">
          <PaintingDetailView
            key={view.paintingId}
            data={view.data}
            artistPaintings={sortedDetailArtistPaintings}
            backLabel={view.returnTo.type === 'timeline' ? t('backToTimeline') : t('backToGallery')}
            tourTitle={tourOverlay?.title ?? null}
            tourText={tourOverlay ? tourOverlay.text : null}
            onBack={() => {
              if (view.returnTo.type === 'timeline') {
                goToTimelineHome();
                return;
              }
              const returnTo = view.returnTo;
              if (
                returnTo.type === 'gallery' &&
                gallerySession?.kind === 'artist' &&
                gallerySession.artistId === returnTo.artistId
              ) {
                openArtistGallery(gallerySession.artistId, gallerySession.data);
              } else if (
                returnTo.type === 'movement-gallery' &&
                gallerySession?.kind === 'movement' &&
                gallerySession.movementId === returnTo.movementId
              ) {
                openMovementGallery(gallerySession.movementId, gallerySession.data);
              } else if (
                returnTo.type === 'tour-gallery' &&
                gallerySession?.kind === 'tour' &&
                gallerySession.tourId === returnTo.tourId
              ) {
                openTourGallery(gallerySession.tourId, gallerySession.data);
              } else if (returnTo.type === 'gallery') {
                openArtistGallery(returnTo.artistId, returnTo.data);
              } else if (returnTo.type === 'movement-gallery') {
                openMovementGallery(returnTo.movementId, returnTo.data);
              } else if (returnTo.type === 'tour-gallery') {
                openTourGallery(returnTo.tourId, returnTo.data);
              } else {
                setView(returnTo);
              }
            }}
            onPaintingClick={handlePaintingClick}
            onCatalogNavigate={handleCatalogNavigate}
            onArtistBio={async () => {
              const artistData = await api.getArtist(view.data.painting.artist_id);
              setView({ type: 'bio', artistId: artistData.artist.id, data: artistData, returnTo: view });
            }}
            onInfluenceArtistClick={handleArtistClick}
            debugMode={effectiveDebugMode}
            debugShowMore={debugShowMore && isCurator}
            onPaintingImageFixed={handlePaintingImageFixed}
            onPaintingCheckupFlagsUpdated={handlePaintingCheckupFlagsUpdated}
            onPaintingRemoved={handlePaintingRemoved}
          />
        </div>
      )}

      {view.type === 'bio' && (
        <div className="home-overlay">
          <ArtistBio
            artist={view.data.artist}
            debugMode={effectiveDebugMode}
            debugShowMore={debugShowMore && isCurator}
            portraitRevision={portraitRevisions[view.data.artist.id]}
            onBack={() => setView(view.returnTo)}
            onEnterGallery={() =>
              openArtistGallery(view.artistId, view.data)
            }
            onArtistPortraitFixed={handleArtistPortraitFixed}
            onArtistCheckupFlagsUpdated={handleArtistCheckupFlagsUpdated}
          />
        </div>
      )}

      {view.type === 'influences' && (
        isCurator ? (
          <InfluencesPage onBack={goToTimelineHome} />
        ) : (
          <div className="curator-login-gate">
            <h2>{t('curatorRequiredTitle')}</h2>
            <p>{t('curatorRequiredBody')}</p>
            <div className="curator-login-gate-actions">
              <button type="button" className="checkup-link-btn" onClick={() => openCuratorLogin('influences')}>
                {t('curatorLogin')}
              </button>
              <button type="button" className="debug-mode-toggle" onClick={goToTimelineHome}>
                {t('backToGalleryBtn')}
              </button>
            </div>
          </div>
        )
      )}

      {view.type === 'tours' && (
        isCurator ? (
          <ToursPage onBack={goToTimelineHome} />
        ) : (
          <div className="curator-login-gate">
            <h2>{t('curatorRequiredTitle')}</h2>
            <p>{t('curatorRequiredBody')}</p>
            <div className="curator-login-gate-actions">
              <button type="button" className="checkup-link-btn" onClick={() => openCuratorLogin('tours')}>
                {t('curatorLogin')}
              </button>
              <button type="button" className="debug-mode-toggle" onClick={goToTimelineHome}>
                {t('backToGalleryBtn')}
              </button>
            </div>
          </div>
        )
      )}

      {view.type === 'translations' && (
        isCurator ? (
          <TranslationsPage onBack={goToTimelineHome} />
        ) : (
          <div className="curator-login-gate">
            <h2>{t('curatorRequiredTitle')}</h2>
            <p>{t('curatorRequiredBody')}</p>
            <div className="curator-login-gate-actions">
              <button type="button" className="checkup-link-btn" onClick={() => openCuratorLogin('translations')}>
                {t('curatorLogin')}
              </button>
              <button type="button" className="debug-mode-toggle" onClick={goToTimelineHome}>
                {t('backToGalleryBtn')}
              </button>
            </div>
          </div>
        )
      )}

      {view.type === 'checkup' && (
        isCurator ? (
          <CheckupPage
            onBack={goToTimelineHome}
            onOpenPainting={handlePaintingClick}
          />
        ) : (
          <div className="curator-login-gate">
            <h2>Curator access required</h2>
            <p>The painting checkup table is available to logged-in curators only.</p>
            <div className="curator-login-gate-actions">
              <button type="button" className="checkup-link-btn" onClick={() => openCuratorLogin('checkup')}>
                Curator login
              </button>
              <button type="button" className="debug-mode-toggle" onClick={goToTimelineHome}>
                Back to gallery
              </button>
            </div>
          </div>
        )
      )}

      <CuratorLoginModal
        open={loginOpen}
        onClose={() => {
          setLoginOpen(false);
          setLoginRedirect(null);
        }}
        onLogin={handleCuratorLogin}
      />

      <ToursPopup
        open={toursPopupOpen}
        onClose={() => setToursPopupOpen(false)}
        onSelectTour={(tourId) => void handleSelectPublishedTour(tourId)}
      />

      {view.type === 'timeline' && (
        <div className="home-page">
          <header className="site-header">
            <div className="site-dev-tools">
              {isCurator ? (
                <>
                  <span className="curator-session-label" title={`Signed in as ${username}`}>
                    {username}
                  </span>
                  <button
                    type="button"
                    className={`debug-mode-toggle${debugMode ? ' debug-mode-toggle-active' : ''}`}
                    onClick={toggleDebugMode}
                    title="Toggle developer image audit mode on painting details and artist bios"
                  >
                    Debug mode{debugMode ? ': ON' : ''}
                  </button>
                  <label
                    className={`debug-show-more-toggle${debugShowMore ? ' debug-show-more-toggle-active' : ''}${!debugMode ? ' debug-show-more-toggle-muted' : ''}`}
                    title="When debug mode is on, open the More search results popup automatically on each painting or artist page"
                  >
                    <input
                      type="checkbox"
                      checked={debugShowMore}
                      onChange={(e) => setDebugShowMoreEnabled(e.target.checked)}
                    />
                    Show more
                  </label>
                  <button
                    type="button"
                    className="checkup-link-btn"
                    onClick={openInfluences}
                    title="Manage influence links"
                  >
                    {t('influences')}
                  </button>
                  <button
                    type="button"
                    className="checkup-link-btn"
                    onClick={openToursEditor}
                    title="Create and edit guided tours"
                  >
                    {t('toursEditor')}
                  </button>
                  <button
                    type="button"
                    className="checkup-link-btn"
                    onClick={openTranslations}
                    title="Review and publish Russian translations"
                  >
                    {t('translations')}
                  </button>
                  <button
                    type="button"
                    className="checkup-link-btn"
                    onClick={openCheckup}
                    title="Open painting image checkup table"
                  >
                    {t('checkup')}
                  </button>
                  <button
                    type="button"
                    className="curator-logout-btn"
                    onClick={handleCuratorLogout}
                    title="Sign out curator session"
                  >
                    {t('curatorLogout')}
                  </button>
                </>
              ) : (
                <button
                  type="button"
                  className="curator-login-btn"
                  onClick={() => openCuratorLogin()}
                  title="Sign in as curator to use debug tools"
                >
                  {t('curatorLogin')}
                </button>
              )}
              <button
                type="button"
                className="checkup-link-btn"
                onClick={() => setToursPopupOpen(true)}
                title={t('tours')}
              >
                {t('tours')}
              </button>
              <LocaleSwitcher onLocaleChange={handleLocaleChange} />
            </div>
            <h1>{t('title')}</h1>
            <p className="site-subtitle">{t('subtitle')}</p>
            <CatalogSearchBar
              onSelectArtist={handleArtistClick}
              onSelectMovement={handleMovementClick}
              onSelectPainting={handlePaintingClick}
            />
          </header>

          <div className="home-timeline-stack">
            {loading && (
              <GalleryLoadingMarker overlay message="Loading art history…" />
            )}
            {galleryEntryLoading && (
              <GalleryLoadingMarker overlay message={galleryEntryLoading} />
            )}
            {portraitsLoading && !loading && !galleryEntryLoading && (
              <GalleryLoadingMarker banner message="Loading portraits…" />
            )}

            <Timeline
              eras={timelineData.eras}
              viewStart={viewStart}
              viewEnd={viewEnd}
              onViewChange={handleViewChange}
              absoluteMin={bounds.min}
              absoluteMax={bounds.max}
              lifespanHighlight={hoveredLifespan}
            />

            {error && <div className="error-banner">{error}</div>}

            {!loading && (
              <>
                <TimelineEventGuides viewStart={viewStart} viewEnd={viewEnd} />
                <div className="home-movements-section">
                  <MovementBands
                    movements={timelineData.movements}
                    artists={artists}
                    portraitRevisions={portraitRevisions}
                    viewStart={viewStart}
                    viewEnd={viewEnd}
                    absoluteMin={bounds.min}
                    absoluteMax={bounds.max}
                    onViewChange={handleViewChange}
                    onArtistClick={handleArtistClick}
                    onMovementClick={handleMovementClick}
                    onArtistHover={setHoveredLifespan}
                    onPortraitsLoadingChange={setPortraitsLoading}
                  />
                </div>
              </>
            )}
          </div>
        </div>
      )}
    </>
  );
}
