import { useEffect, useState, useRef, useCallback } from "react";
import { ProgressSpinner } from 'primereact/progressspinner';
import { Dialog } from 'primereact/dialog';
import { Image } from 'primereact/image';
import { API_URL } from '../config';

const MEME_API_URL = `${API_URL}/memes/list_memes`;
const BASE_IMAGE_URL = "https://codey.lol/meme";

const Memes = () => {
  const [images, setImages] = useState([]);
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(false);
  const [hasMore, setHasMore] = useState(true);
  const [selectedImage, setSelectedImage] = useState(null);
  const observerRef = useRef();
  const theme = document.documentElement.getAttribute("data-theme")
  const loadImages = async (pageNum, attempt = 0) => {
    if (loading || !hasMore) return;
    setLoading(true);
    try {
      const res = await fetch(`${MEME_API_URL}?page=${pageNum}`);

      if (res.status === 429) {
        const backoff = Math.min(1000 * Math.pow(2, attempt), 10000); // max 10s
        console.warn(`Rate limited. Retrying in ${backoff}ms`);
        setTimeout(() => {
          loadImages(pageNum, attempt + 1);
        }, backoff);
        return;
      }

      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const data = await res.json();

      const newMemes = data?.memes || [];

      if (newMemes.length === 0 || data.paging.current >= data.paging.of) {
        setHasMore(false);
      }

      const imageObjects = newMemes.map(m => ({
        id: m.id,
        timestamp: new Date(m.timestamp * 1000)
          .toString().split(" ")
          .splice(0, 4).join(" "),
        url: `${BASE_IMAGE_URL}/${m.id}.png`,
      }));

      setImages(prev => [...prev, ...imageObjects]);
      setPage(prev => prev + 1);
    } catch (e) {
      console.error("Failed to load memes", e);
      toast.error("Failed to load more memes.");
    } finally {
      setLoading(false);
    }
  };

  const lastImageRef = useCallback(node => {
    if (loading) return;
    if (observerRef.current) observerRef.current.disconnect();
    observerRef.current = new IntersectionObserver(entries => {
      if (entries[0].isIntersecting && hasMore) {
        loadImages(page);
      }
    });
    if (node) observerRef.current.observe(node);
  }, [loading, hasMore, page]);

  useEffect(() => {
    loadImages(1);
  }, []);

  return (
    <>
      <div className="grid-container">
        {images.map((img, i) => {
          const isLast = i === images.length - 1;
          return (
            <div
              key={img.id}
              className="grid-item"
              ref={isLast ? lastImageRef : null}
              onClick={() => setSelectedImage(img)}
              style={{ cursor: 'pointer' }}
            >
              <Image
                src={img.url}
                alt={`meme-${img.id}`}
                imageClassName="meme-img"
                loading="lazy"
              />
            </div>
          );
        })}
        {loading && (
          <div className="loading">
            <ProgressSpinner style={{ width: '50px', height: '50px' }} />
          </div>
        )}
      </div>

      {/* Dialog for enlarged image */}
      <Dialog
        header={`Meme #${selectedImage?.id} - ${selectedImage?.timestamp}`}
        visible={!!selectedImage}
        onHide={() => setSelectedImage(null)}
        style={{ width: '90vw', maxWidth: '720px' }}
        className={`d-${theme}`}
        modal
        closable
        dismissableMask={true}
      >
        {selectedImage && (
          <img
            src={selectedImage.url}
            alt={`meme-${selectedImage.id}`}
            style={{
              maxWidth: '100%',
              maxHeight: '70vh', // restrict height to viewport height
              objectFit: 'contain',
              display: 'block',
              margin: '0 auto',
              borderRadius: '6px',
            }}
          />

        )}
      </Dialog>
    </>
  );
};

export default Memes;
