import { useEffect, useState, type SyntheticEvent } from 'react';
import type { InfluenceLink, Painting, PaintingDetail } from '../types';
import { api, debugImageProxyUrl, imageUrl, paintingImageUrl, type DebugImageSearchResult, type FixPaintingImageResult } from '../api/client';
import PaintingLightbox from './PaintingLightbox';
import './PaintingDetail.css';

interface Props {
  data: PaintingDetail;
  artistPaintings?: Painting[];
  onBack: () => void;
  onPaintingClick: (paintingId: number) => void;
  onCatalogNavigate: (paintingId: number) => void;
  onArtistBio: () => void;
  onInfluenceArtistClick?: (artistId: number) => void;
  debugMode?: boolean;
  onPaintingImageFixed?: (
    paintingId: number,
    fixResult: FixPaintingImageResult
  ) => void | Promise<void>;
  onPaintingCheckupFlagsUpdated?: (
    paintingId: number,
    flags: { checked: boolean; fixed: boolean }
  ) => void | Promise<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}
            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 })}
          alt={inf.title || 'Painting'}
          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 = [],
  onBack,
  onPaintingClick,
  onCatalogNavigate,
  onArtistBio,
  onInfluenceArtistClick,
  debugMode = false,
  onPaintingImageFixed,
  onPaintingCheckupFlagsUpdated,
}: Props) {
  const { painting, influencedBy, influenced } = data;
  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 imageSrc = `${paintingImageUrl(painting)}${paintingImageUrl(painting).includes('?') ? '&' : '?'}v=${imageVersion}`;

  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);
  }, [painting.id]);

  useEffect(() => {
    if (!debugMode) {
      setDebugSearch(null);
      setDebugError(null);
      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, painting.id, painting.title, painting.artist_name]);

  const handleFixImage = async () => {
    if (!debugSearch?.imageUrl || fixing) return;
    setFixing(true);
    setDebugError(null);
    try {
      const fixResult = await api.fixPaintingImage(painting.id, debugSearch.imageUrl, {
        searchUrl: debugSearch.searchUrl,
        source: debugSearch.source,
        thumbUrl: debugSearch.thumbUrl,
      });
      setImageVersion((v) => v + 1);
      if (onPaintingImageFixed) {
        await onPaintingImageFixed(painting.id, fixResult);
      }
    } catch (err) {
      setDebugError(err instanceof Error ? err.message : 'Could not replace image.');
    } finally {
      setFixing(false);
    }
  };

  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);
    }
  };

  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' : ''}`}>
      <header className="painting-header">
        <button className="back-btn" onClick={onBack}>← Back to Gallery</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">
                {' · '}
                {catalogIndex + 1} of {artistPaintings.length}
              </span>
            )}
          </p>
        </div>
        <button className="bio-btn" onClick={onArtistBio}>
          About {painting.artist_name}
        </button>
      </header>

      <div className="painting-layout">
        <aside className="influence-panel influence-left">
          <h3>Influenced By</h3>
          {influencedBy.length === 0 ? (
            <p className="no-influences">No documented influences for this work.</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 painting-frame-clickable"
              role="button"
              tabIndex={0}
              onClick={() => setFullscreen(true)}
              onKeyDown={(e) => {
                if (e.key === 'Enter' || e.key === ' ') {
                  e.preventDefault();
                  setFullscreen(true);
                }
              }}
              title="View full screen"
              aria-label={`View ${painting.title} full screen`}
            >
              <img src={imageSrc} alt={painting.title} onError={handleImageError} draggable={false} />
            </div>

            {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>
          {painting.description && (
            <div className="painting-description">
              <p>{painting.description}</p>
            </div>
          )}
        </main>

        <aside className="influence-panel influence-right">
          <h3>Influenced</h3>
          {influenced.length === 0 ? (
            <p className="no-influences">No documented works influenced by this painting yet.</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" 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 && <p className="debug-image-status">Searching…</p>}
          {debugError && <p className="debug-image-error">{debugError}</p>}
          {!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';
              }}
            />
          )}
          {!debugLoading && debugSearch && !debugSearch.imageUrl && !debugError && (
            <p className="debug-image-status">No Google image result found.</p>
          )}
          <div className="debug-action-buttons">
            <button
              type="button"
              className="debug-checked-btn"
              onClick={handleMarkChecked}
              disabled={!!painting.checkup_checked || markingChecked}
            >
              {markingChecked ? '…' : 'Checked'}
            </button>
            <button
              type="button"
              className="debug-fix-btn"
              onClick={handleFixImage}
              disabled={fixing || debugLoading || !debugSearch?.imageUrl}
            >
              {fixing ? '…' : 'Fix it'}
            </button>
          </div>
        </aside>
      )}

      {fullscreen && (
        <PaintingLightbox
          src={imageSrc}
          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>
  );
}
