import { useCallback, useEffect, useState, type SyntheticEvent } from 'react';
import { useTranslation } from 'react-i18next';
import type { InfluenceLink, Painting, PaintingDetail } from '../types';
import { api, debugImageProxyUrl, imageUrl, paintingImageUrl, type DebugImageSearchResult, type DebugImageSearchResultItem, type FixPaintingImageResult } from '../api/client';
import DebugSearchResultsModal from './DebugSearchResultsModal';
import DebugUploadButton from './DebugUploadButton';
import GalleryLoadingMarker from './GalleryLoadingMarker';
import PaintingAnnotationsPanel, { PaintingAnnotationMarkers } from './PaintingAnnotations';
import PaintingLightbox from './PaintingLightbox';
import './PaintingDetail.css';
import './GalleryLoadingMarker.css';

interface Props {
  data: PaintingDetail;
  artistPaintings?: Painting[];
  backLabel?: string;
  tourTitle?: string | null;
  tourText?: string | null;
  onBack: () => void;
  onPaintingClick: (paintingId: number) => void;
  onCatalogNavigate: (paintingId: number) => void;
  onArtistBio: () => void;
  onInfluenceArtistClick?: (artistId: number) => void;
  isCurator?: boolean;
  /** When false, hide the Checked action (needs checkup permission). Defaults to true when debugMode is on. */
  canCheckup?: boolean;
  debugMode?: boolean;
  debugShowMore?: boolean;
  onPaintingImageFixed?: (
    paintingId: number,
    fixResult: FixPaintingImageResult
  ) => void | Promise<void>;
  onPaintingCheckupFlagsUpdated?: (
    paintingId: number,
    flags: { checked: boolean; fixed: boolean }
  ) => void | Promise<void>;
  onPaintingRemoved?: (paintingId: number, artistId: number) => void | Promise<void>;
  onCuratorNotesUpdated?: (paintingId: number, curatorNotes: string) => void;
}

function influenceKey(inf: InfluenceLink, index: number): string {
  if (inf.source_type === 'movement') return `movement-${inf.movement_id ?? inf.movement_name}-${index}`;
  if (inf.source_type === 'artist') return `artist-${inf.source_artist_id ?? inf.source_artist_name}-${index}`;
  return `painting-${inf.id}-${index}`;
}

function periodLabel(inf: InfluenceLink): string | null {
  if (inf.period_note) return inf.period_note;
  if (inf.period_start_year != null && inf.period_end_year != null) {
    return `${inf.period_start_year}–${inf.period_end_year}`;
  }
  if (inf.period_start_year != null) return `from ${inf.period_start_year}`;
  return null;
}

function InfluenceCard({
  inf,
  onPaintingClick,
  onInfluenceArtistClick,
}: {
  inf: InfluenceLink;
  onPaintingClick: (id: number) => void;
  onInfluenceArtistClick?: (artistId: number) => void;
}) {
  const aspects = inf.aspects
    ? inf.aspects.split(',').map((a) => a.trim()).filter(Boolean)
    : [];
  const period = periodLabel(inf);
  const sourceType = inf.source_type || 'painting';

  const meta = (
    <>
      {aspects.length > 0 && (
        <div className="influence-aspects">
          {aspects.map((aspect) => (
            <span key={aspect} className="aspect-tag">{aspect}</span>
          ))}
        </div>
      )}
      {period && <p className="influence-period">{period}</p>}
      {inf.notes && <p className="influence-notes">{inf.notes}</p>}
      {inf.quote && (
        <blockquote className="influence-quote">
          <p>&ldquo;{inf.quote}&rdquo;</p>
          {(inf.source_author || inf.source) && (
            <footer>
              — {inf.source_author}
              {inf.source && <cite>, {inf.source}</cite>}
            </footer>
          )}
        </blockquote>
      )}
      {inf.source_url && (
        <a
          className="influence-source-link"
          href={inf.source_url}
          target="_blank"
          rel="noopener noreferrer"
          onClick={(e) => e.stopPropagation()}
        >
          Read source: {inf.source_author || inf.source || 'Reference'}
        </a>
      )}
      {inf.confidence === 'discovered' && inf.discovered_via && (
        <span className="influence-discovered-tag">Discovered via {inf.discovered_via}</span>
      )}
    </>
  );

  if (sourceType === 'movement') {
    return (
      <article className="influence-card-expanded influence-card-movement">
        <div
          className="influence-movement-swatch"
          style={{ background: inf.movement_color || '#8B7355' }}
          aria-hidden
        />
        <div className="influence-body">
          <div className="influence-title-btn influence-title-static">
            <strong>{inf.movement_name}</strong>
            <span>Art movement</span>
          </div>
          {meta}
        </div>
      </article>
    );
  }

  if (sourceType === 'artist') {
    const artistId = inf.source_artist_id;
    const artistName = inf.source_artist_name || 'Unknown artist';
    return (
      <article className="influence-card-expanded influence-card-artist">
        <button
          type="button"
          className="influence-image-btn influence-portrait-btn"
          onClick={() => artistId && onInfluenceArtistClick?.(artistId)}
          title={`View ${artistName}`}
          disabled={!artistId || !onInfluenceArtistClick}
        >
          <img
            src={imageUrl(inf.artist_portrait)}
            alt={artistName}
            loading="lazy"
            decoding="async"
            onError={(e) => {
              (e.target as HTMLImageElement).src = '/placeholder-portrait.svg';
            }}
          />
        </button>
        <div className="influence-body">
          <button
            type="button"
            className="influence-title-btn"
            onClick={() => artistId && onInfluenceArtistClick?.(artistId)}
            disabled={!artistId || !onInfluenceArtistClick}
          >
            <strong>{artistName}</strong>
            <span>Artist influence</span>
          </button>
          {meta}
        </div>
      </article>
    );
  }

  if (!inf.id) return null;

  return (
    <article className="influence-card-expanded">
      <button
        type="button"
        className="influence-image-btn"
        onClick={() => onPaintingClick(inf.id!)}
        title={`View ${inf.title}`}
      >
        <img
          src={paintingImageUrl({ id: inf.id, image_path: inf.image_path }) ?? '/placeholder-art.svg'}
          alt={inf.title || 'Painting'}
          loading="lazy"
          decoding="async"
          onError={(e) => {
            (e.target as HTMLImageElement).src = '/placeholder-art.svg';
          }}
        />
      </button>

      <div className="influence-body">
        <button type="button" className="influence-title-btn" onClick={() => onPaintingClick(inf.id!)}>
          <strong>{inf.title}</strong>
          <span>{inf.artist_name}{inf.year ? `, ${inf.year}` : ''}</span>
        </button>
        {meta}
      </div>
    </article>
  );
}

export default function PaintingDetailView({
  data,
  artistPaintings = [],
  backLabel = '← Back to Gallery',
  tourTitle = null,
  tourText = null,
  onBack,
  onPaintingClick,
  onCatalogNavigate,
  onArtistBio,
  onInfluenceArtistClick,
  isCurator = false,
  canCheckup = true,
  debugMode = false,
  debugShowMore = false,
  onPaintingImageFixed,
  onPaintingCheckupFlagsUpdated,
  onPaintingRemoved,
  onCuratorNotesUpdated,
}: Props) {
  const { t } = useTranslation('painting');
  const { painting, influencedBy, influenced, annotations = [] } = data;
  const inTour = tourText != null;
  const [curatorNotes, setCuratorNotes] = useState(painting.curator_notes ?? '');
  const [editingNotes, setEditingNotes] = useState(false);
  const [notesDraft, setNotesDraft] = useState(painting.curator_notes ?? '');
  const [savingNotes, setSavingNotes] = useState(false);
  const [notesError, setNotesError] = useState<string | null>(null);
  const [fullscreen, setFullscreen] = useState(false);
  const [imageVersion, setImageVersion] = useState(0);
  const [debugSearch, setDebugSearch] = useState<DebugImageSearchResult | null>(null);
  const [debugLoading, setDebugLoading] = useState(false);
  const [debugError, setDebugError] = useState<string | null>(null);
  const [fixing, setFixing] = useState(false);
  const [markingChecked, setMarkingChecked] = useState(false);
  const [moreOpen, setMoreOpen] = useState(false);
  const [moreLoading, setMoreLoading] = useState(false);
  const [moreError, setMoreError] = useState<string | null>(null);
  const [moreResults, setMoreResults] = useState<Awaited<ReturnType<typeof api.getPaintingDebugImageSearchMore>> | null>(null);
  const [applyingUrl, setApplyingUrl] = useState<string | null>(null);
  const [clearing, setClearing] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [uploadStatus, setUploadStatus] = useState<string | null>(null);
  const [removing, setRemoving] = useState(false);
  const [activeAnnotationId, setActiveAnnotationId] = useState<number | null>(null);

  const imageSrc = paintingImageUrl(painting, imageVersion || undefined);
  const displayImageSrc = uploading ? null : imageSrc;
  const imageCleared = !painting.image_path && !painting.thumbnail_path && !!painting.checkup_fixed;

  const catalogIndex = artistPaintings.findIndex((p) => p.id === painting.id);
  const previousPainting = catalogIndex > 0 ? artistPaintings[catalogIndex - 1] : null;
  const nextPainting =
    catalogIndex >= 0 && catalogIndex < artistPaintings.length - 1
      ? artistPaintings[catalogIndex + 1]
      : null;
  const showCatalogNav = artistPaintings.length > 1 && catalogIndex >= 0;

  useEffect(() => {
    setFullscreen(false);
    setImageVersion(0);
    setMoreOpen(false);
    setMoreResults(null);
    setMoreError(null);
    setActiveAnnotationId(null);
    setRemoving(false);
    setFixing(false);
    setClearing(false);
    setUploading(false);
    setUploadStatus(null);
    setMarkingChecked(false);
    setApplyingUrl(null);
    setMoreLoading(false);
    const notes = painting.curator_notes ?? '';
    setCuratorNotes(notes);
    setNotesDraft(notes);
    setEditingNotes(false);
    setSavingNotes(false);
    setNotesError(null);
  }, [painting.id, painting.curator_notes]);

  useEffect(() => {
    if (!debugMode) {
      setDebugSearch(null);
      setDebugError(null);
      setMoreOpen(false);
      return;
    }
    if (uploading) {
      return;
    }

    let cancelled = false;
    setDebugLoading(true);
    setDebugError(null);
    setDebugSearch(null);

    api.getPaintingDebugImageSearch(painting.id)
      .then((result) => {
        if (!cancelled) setDebugSearch(result);
      })
      .catch(() => {
        if (!cancelled) setDebugError('Google image search failed.');
      })
      .finally(() => {
        if (!cancelled) setDebugLoading(false);
      });

    return () => {
      cancelled = true;
    };
  }, [debugMode, uploading, painting.id, painting.title, painting.artist_name]);

  const startEditingNotes = () => {
    setNotesDraft(curatorNotes);
    setNotesError(null);
    setEditingNotes(true);
  };

  const cancelEditingNotes = () => {
    setNotesDraft(curatorNotes);
    setNotesError(null);
    setEditingNotes(false);
  };

  const saveCuratorNotes = async () => {
    setSavingNotes(true);
    setNotesError(null);
    try {
      const result = await api.updatePaintingCuratorNotes(painting.id, notesDraft);
      setCuratorNotes(result.curatorNotes);
      setNotesDraft(result.curatorNotes);
      setEditingNotes(false);
      onCuratorNotesUpdated?.(painting.id, result.curatorNotes);
    } catch {
      setNotesError(t('curatorNotesSaveFailed'));
    } finally {
      setSavingNotes(false);
    }
  };

  const applyImageUpdate = async (fixResult: FixPaintingImageResult) => {
    setImageVersion((v) => v + 1);
    if (onPaintingImageFixed) {
      await onPaintingImageFixed(painting.id, fixResult);
    }
  };

  const applyFixFromSearch = async (
    imageUrl: string,
    context: { searchUrl: string; source: string; thumbUrl?: string }
  ) => {
    const fixResult = await api.fixPaintingImage(painting.id, imageUrl, context);
    await applyImageUpdate(fixResult);
    setDebugSearch((prev) =>
      prev
        ? { ...prev, imageUrl, thumbUrl: context.thumbUrl ?? prev.thumbUrl, source: context.source }
        : prev
    );
  };

  const handleFixImage = async () => {
    if (!debugSearch?.imageUrl || fixing) return;
    setFixing(true);
    setDebugError(null);
    try {
      await applyFixFromSearch(debugSearch.imageUrl, {
        searchUrl: debugSearch.searchUrl,
        source: debugSearch.source,
        thumbUrl: debugSearch.thumbUrl,
      });
    } catch (err) {
      setDebugError(err instanceof Error ? err.message : 'Could not replace image.');
    } finally {
      setFixing(false);
    }
  };

  const handleOpenMore = useCallback(async () => {
    setMoreOpen(true);
    setMoreLoading(true);
    setMoreError(null);
    setMoreResults(null);
    try {
      const results = await api.getPaintingDebugImageSearchMore(painting.id);
      setMoreResults(results);
    } catch {
      setMoreError('Could not load search results.');
    } finally {
      setMoreLoading(false);
    }
  }, [painting.id]);

  useEffect(() => {
    if (!debugMode || !debugShowMore) return;
    void handleOpenMore();
  }, [debugMode, debugShowMore, painting.id, handleOpenMore]);

  const handleSelectMoreResult = async (item: DebugImageSearchResultItem) => {
    if (fixing || applyingUrl) return;
    setApplyingUrl(item.imageUrl);
    setMoreError(null);
    setDebugError(null);
    try {
      const searchUrl = moreResults?.searchUrl ?? debugSearch?.searchUrl ?? '';
      await applyFixFromSearch(item.imageUrl, {
        searchUrl,
        source: item.source,
        thumbUrl: item.thumbUrl,
      });
      setMoreOpen(false);
    } catch (err) {
      setMoreError(err instanceof Error ? err.message : 'Could not replace image.');
    } finally {
      setApplyingUrl(null);
    }
  };

  const handleMarkChecked = async () => {
    if (painting.checkup_checked || markingChecked) return;
    setMarkingChecked(true);
    setDebugError(null);
    try {
      const updated = await api.updatePaintingCheckupFlags(painting.id, { checked: true });
      await onPaintingCheckupFlagsUpdated?.(painting.id, updated);
    } catch (err) {
      setDebugError(err instanceof Error ? err.message : 'Could not mark as checked.');
    } finally {
      setMarkingChecked(false);
    }
  };

  const handleClearImage = async () => {
    if (clearing || fixing || uploading) return;
    setClearing(true);
    setDebugError(null);
    try {
      const result = await api.clearPaintingImage(painting.id);
      await applyImageUpdate(result);
    } catch (err) {
      setDebugError(err instanceof Error ? err.message : 'Could not clear image.');
    } finally {
      setClearing(false);
    }
  };

  const handleUploadPress = () => {
    setDebugSearch(null);
    setDebugLoading(false);
    setMoreOpen(false);
    setMoreResults(null);
    setMoreError(null);
    setDebugError(null);
  };

  const handleUploadFile = async (file: File) => {
    if (uploading || fixing || clearing) return;
    handleUploadPress();
    setUploading(true);
    setUploadStatus('Reading file…');
    try {
      setUploadStatus('Uploading…');
      const result = await api.uploadPaintingImage(painting.id, file);
      await applyImageUpdate(result);
      setUploadStatus('Upload complete.');
    } catch (err) {
      setUploadStatus(null);
      setDebugError(err instanceof Error ? err.message : 'Could not upload image.');
    } finally {
      setUploading(false);
    }
  };

  const handleRemoveEntry = async () => {
    if (removing || fixing || clearing || uploading || !onPaintingRemoved) return;
    setRemoving(true);
    setDebugError(null);
    try {
      await onPaintingRemoved(painting.id, painting.artist_id);
    } catch (err) {
      setDebugError(err instanceof Error ? err.message : 'Could not remove painting.');
      setRemoving(false);
    }
  };

  useEffect(() => {
    if (fullscreen) return;

    const onKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'ArrowLeft' && previousPainting) {
        e.preventDefault();
        onCatalogNavigate(previousPainting.id);
      } else if (e.key === 'ArrowRight' && nextPainting) {
        e.preventDefault();
        onCatalogNavigate(nextPainting.id);
      }
    };

    window.addEventListener('keydown', onKeyDown);
    return () => window.removeEventListener('keydown', onKeyDown);
  }, [fullscreen, previousPainting, nextPainting, onCatalogNavigate]);

  const handleImageError = (e: SyntheticEvent<HTMLImageElement>) => {
    e.currentTarget.src = '/placeholder-art.svg';
  };

  return (
    <div className={`painting-detail${fullscreen ? ' painting-detail-fullscreen-active' : ''}`}>
      {uploading && (
        <GalleryLoadingMarker
          overlay
          className="debug-upload-page-overlay"
          message={uploadStatus ?? 'Loading…'}
        />
      )}
      <header className="painting-header">
        <button className="back-btn" onClick={onBack}>{backLabel}</button>
        <div className="painting-title-block">
          <h1>{painting.title}</h1>
          <p className="painting-meta">
            {painting.artist_name}
            {painting.year && ` · ${painting.year}`}
            {showCatalogNav && (
              <span className="painting-catalog-position">
                {' · '}
                {inTour
                  ? t('tourStopPosition', { current: catalogIndex + 1, total: artistPaintings.length })
                  : `${catalogIndex + 1} of ${artistPaintings.length}`}
              </span>
            )}
          </p>
        </div>
        <button className="bio-btn" onClick={onArtistBio}>
          {t('aboutArtist', { name: painting.artist_name })}
        </button>
      </header>

      <div className="painting-layout">
        <aside className="influence-panel influence-left">
          <h3>{t('influencedBy')}</h3>
          {influencedBy.length === 0 ? (
            <p className="no-influences">{t('noInfluences')}</p>
          ) : (
            <div className="influence-list">
              {influencedBy.map((inf, index) => (
                <InfluenceCard
                  key={influenceKey(inf, index)}
                  inf={inf}
                  onPaintingClick={onPaintingClick}
                  onInfluenceArtistClick={onInfluenceArtistClick}
                />
              ))}
            </div>
          )}
        </aside>

        <main className="painting-center">
          <div className="painting-center-nav">
            {showCatalogNav && (
              <button
                type="button"
                className="painting-nav-btn painting-nav-prev"
                onClick={() => previousPainting && onCatalogNavigate(previousPainting.id)}
                disabled={!previousPainting}
                title={previousPainting ? `Previous: ${previousPainting.title}` : 'No earlier work'}
                aria-label={
                  previousPainting ? `Previous painting: ${previousPainting.title}` : 'No earlier work'
                }
              >
                ‹
              </button>
            )}

            <div
              className={`painting-frame-large${displayImageSrc ? ' painting-frame-clickable' : ' painting-frame-empty'}${imageCleared && !uploading ? ' painting-frame-cleared' : ''}${uploading ? ' painting-frame-uploading' : ''}`}
              role={displayImageSrc ? 'button' : undefined}
              tabIndex={displayImageSrc ? 0 : undefined}
              onClick={displayImageSrc ? () => setFullscreen(true) : undefined}
              onKeyDown={
                displayImageSrc
                  ? (e) => {
                      if (e.key === 'Enter' || e.key === ' ') {
                        e.preventDefault();
                        setFullscreen(true);
                      }
                    }
                  : undefined
              }
              title={displayImageSrc ? 'View full screen' : undefined}
              aria-label={displayImageSrc ? `View ${painting.title} full screen` : `${painting.title} (no image)`}
            >
              <div className="painting-frame-image-wrap">
                {displayImageSrc ? (
                  <img src={displayImageSrc} alt={painting.title} onError={handleImageError} draggable={false} />
                ) : null}
                {displayImageSrc && annotations.length > 0 && (
                  <PaintingAnnotationMarkers
                    annotations={annotations}
                    activeId={activeAnnotationId}
                    onSelect={setActiveAnnotationId}
                  />
                )}
              </div>
            </div>

            {annotations.length > 0 && (
              <PaintingAnnotationsPanel
                annotations={annotations}
                activeId={activeAnnotationId}
                onSelect={setActiveAnnotationId}
              />
            )}

            {showCatalogNav && (
              <button
                type="button"
                className="painting-nav-btn painting-nav-next"
                onClick={() => nextPainting && onCatalogNavigate(nextPainting.id)}
                disabled={!nextPainting}
                title={nextPainting ? `Next: ${nextPainting.title}` : 'No later work'}
                aria-label={nextPainting ? `Next painting: ${nextPainting.title}` : 'No later work'}
              >
                ›
              </button>
            )}
          </div>
          {inTour && (
            <aside className="tour-stop-panel" aria-label={t('tourNotes')}>
              <h3>{tourTitle ? t('tourNotesFor', { title: tourTitle }) : t('tourNotes')}</h3>
              {tourText.trim() ? (
                <p className="tour-stop-body">{tourText}</p>
              ) : (
                <p className="tour-stop-empty">{t('tourNotesEmpty')}</p>
              )}
            </aside>
          )}
          {(isCurator || curatorNotes.trim()) && (
            <aside className="curator-notes-panel" aria-label={t('curatorNotes')}>
              <div className="curator-notes-header">
                <h3>{t('curatorNotes')}</h3>
                {isCurator && !editingNotes && (
                  <button
                    type="button"
                    className="curator-notes-edit-btn"
                    onClick={startEditingNotes}
                  >
                    {t('curatorNotesEdit')}
                  </button>
                )}
              </div>
              {editingNotes ? (
                <div className="curator-notes-editor">
                  <textarea
                    className="curator-notes-textarea"
                    value={notesDraft}
                    onChange={(e) => setNotesDraft(e.target.value)}
                    rows={6}
                    disabled={savingNotes}
                    aria-label={t('curatorNotes')}
                  />
                  {notesError && <p className="curator-notes-error">{notesError}</p>}
                  <div className="curator-notes-actions">
                    <button
                      type="button"
                      className="curator-notes-save-btn"
                      onClick={saveCuratorNotes}
                      disabled={savingNotes}
                    >
                      {savingNotes ? t('curatorNotesSaving') : t('curatorNotesSave')}
                    </button>
                    <button
                      type="button"
                      className="curator-notes-cancel-btn"
                      onClick={cancelEditingNotes}
                      disabled={savingNotes}
                    >
                      {t('curatorNotesCancel')}
                    </button>
                  </div>
                </div>
              ) : curatorNotes.trim() ? (
                <p className="curator-notes-body">{curatorNotes}</p>
              ) : (
                <p className="curator-notes-empty">{t('curatorNotesEmpty')}</p>
              )}
            </aside>
          )}
          {painting.description && (
            <div className="painting-description">
              <p>{painting.description}</p>
            </div>
          )}
        </main>

        <aside className="influence-panel influence-right">
          <h3>{t('influenced')}</h3>
          {influenced.length === 0 ? (
            <p className="no-influences">{t('noInfluencedWorks')}</p>
          ) : (
            <div className="influence-list">
              {influenced.map((inf, index) => (
                <InfluenceCard
                  key={influenceKey(inf, index)}
                  inf={inf}
                  onPaintingClick={onPaintingClick}
                  onInfluenceArtistClick={onInfluenceArtistClick}
                />
              ))}
            </div>
          )}
        </aside>
      </div>

      {debugMode && (
        <aside
          className={`debug-image-panel${uploading ? ' debug-image-panel-blocked' : ''}`}
          aria-label="Debug image search"
        >
          <h4>{debugSearch?.sourceLabel ?? 'Google image search'}</h4>
          <p className="debug-image-query">
            {debugSearch?.query ?? `${painting.artist_name} ${painting.title} painting`}
          </p>
          {debugLoading && !uploading && <p className="debug-image-status">Searching…</p>}
          {debugError && !uploading && <p className="debug-image-error">{debugError}</p>}
          {!uploading && !debugLoading && debugSearch?.imageUrl && (
            <img
              className="debug-image-preview"
              src={debugImageProxyUrl(debugSearch.imageUrl, {
                searchUrl: debugSearch.searchUrl,
                source: debugSearch.source,
              })}
              alt={`Google search result for ${debugSearch.query}`}
              onError={(e) => {
                (e.target as HTMLImageElement).src = '/placeholder-art.svg';
              }}
            />
          )}
          {!uploading && !debugLoading && debugSearch && !debugSearch.imageUrl && !debugError && (
            <p className="debug-image-status">No Google image result found.</p>
          )}
          <div className="debug-action-buttons">
            {canCheckup && (
              <button
                type="button"
                className="debug-checked-btn"
                onClick={handleMarkChecked}
                disabled={!!painting.checkup_checked || markingChecked || uploading}
              >
                {markingChecked ? '…' : 'Checked'}
              </button>
            )}
            <button
              type="button"
              className="debug-fix-btn"
              onClick={handleFixImage}
              disabled={fixing || debugLoading || uploading || !debugSearch?.imageUrl}
            >
              {fixing ? '…' : 'Fix it'}
            </button>
            <button
              type="button"
              className="debug-more-btn"
              onClick={handleOpenMore}
              disabled={debugLoading || moreLoading || uploading}
            >
              {moreLoading ? '…' : 'More'}
            </button>
          </div>
          <div className="debug-action-buttons debug-action-buttons-secondary">
            <button
              type="button"
              className="debug-clear-btn"
              onClick={handleClearImage}
              disabled={clearing || fixing || uploading || imageCleared}
            >
              {clearing ? '…' : 'Clear'}
            </button>
            <DebugUploadButton
              uploading={uploading}
              disabled={fixing || clearing}
              onUploadPress={handleUploadPress}
              onFileSelected={handleUploadFile}
            />
          </div>
          <div className="debug-action-buttons debug-action-buttons-danger">
            <button
              type="button"
              className="debug-remove-btn"
              onClick={handleRemoveEntry}
              disabled={removing || fixing || clearing || uploading}
            >
              {removing ? '…' : 'Remove entry'}
            </button>
          </div>
        </aside>
      )}

      <DebugSearchResultsModal
        open={moreOpen && !uploading}
        title="Choose painting image"
        data={moreResults}
        loading={moreLoading}
        error={moreError}
        applyingUrl={applyingUrl}
        onClose={() => setMoreOpen(false)}
        onSelect={handleSelectMoreResult}
      />

      {fullscreen && displayImageSrc && (
        <PaintingLightbox
          src={displayImageSrc}
          alt={painting.title}
          title={painting.title}
          subtitle={[painting.artist_name, painting.year ? String(painting.year) : '']
            .filter(Boolean)
            .join(' · ')}
          closeHint="Click to return to painting details"
          onClose={() => setFullscreen(false)}
        />
      )}
    </div>
  );
}
