'use client';

import { useEffect, useRef, useState } from 'react';
import { XIcon } from 'lucide-react';
import { AnimatePresence, motion } from 'motion/react';
import { type GeneratedImage, useGeneratedImages } from '@/hooks/useGeneratedImages';
import { cn } from '@/lib/shadcn/utils';

const MotionPanel = motion.create('div');

interface ImageCardProps {
  image: GeneratedImage;
  onDismiss: () => void;
}

function ImageCard({ image, onDismiss }: ImageCardProps) {
  const src = image.imageUrl;

  return (
    <MotionPanel
      key={image.id}
      layout
      initial={{ opacity: 0, scale: 0.92, y: 8 }}
      animate={{ opacity: 1, scale: 1, y: 0 }}
      exit={{ opacity: 0, scale: 0.92, y: 8 }}
      transition={{ duration: 0.25, ease: 'easeOut' }}
      className="bg-background border-input/50 relative overflow-hidden rounded-xl border shadow-xl"
    >
      {/* eslint-disable-next-line @next/next/no-img-element */}
      <img src={src} alt={image.prompt} className="block max-h-[360px] w-full object-contain" />
      {image.prompt && (
        <div className="bg-background/80 px-3 py-1.5 backdrop-blur-sm">
          <p className="text-muted-foreground line-clamp-2 text-xs">{image.prompt}</p>
        </div>
      )}
      <button
        onClick={onDismiss}
        className={cn(
          'bg-background/70 hover:bg-background absolute top-2 right-2 rounded-full p-1 backdrop-blur-sm transition-colors'
        )}
        aria-label="Dismiss image"
      >
        <XIcon className="text-muted-foreground size-3.5" />
      </button>
    </MotionPanel>
  );
}

interface GeneratedImagePanelProps {
  chatOpen?: boolean;
}

/**
 * Listens for images generated by the agent and shows the most recent one.
 * When chat is open, repositions to the top-right corner to avoid covering the transcript.
 *
 * HACK HERE: swap for a gallery view, a fullscreen modal, download button, etc.
 */
export function GeneratedImagePanel({ chatOpen = false }: GeneratedImagePanelProps) {
  const images = useGeneratedImages();
  const [dismissed, setDismissed] = useState<Set<string>>(new Set());
  const prevLengthRef = useRef(0);

  // Auto-scroll to latest image
  useEffect(() => {
    if (images.length > prevLengthRef.current) {
      prevLengthRef.current = images.length;
    }
  }, [images]);

  const visible = images.filter((img) => !dismissed.has(img.id));
  const latest = visible.at(-1);

  const dismiss = (id: string) => {
    setDismissed((prev) => new Set([...prev, id]));
  };

  return (
    <div
      className={cn(
        'pointer-events-none fixed z-40 flex justify-center px-4',
        chatOpen
          ? 'top-16 right-4 bottom-auto left-auto justify-end'
          : 'inset-x-0 bottom-36 md:bottom-44'
      )}
    >
      <div className={cn('pointer-events-auto', chatOpen ? 'w-48' : 'w-full max-w-sm')}>
        <AnimatePresence mode="popLayout">
          {latest && (
            <ImageCard key={latest.id} image={latest} onDismiss={() => dismiss(latest.id)} />
          )}
        </AnimatePresence>
      </div>
    </div>
  );
}
