'use client';

import { isSupportAttachmentImage, type Passenger } from '@edr/types';
import { FileText, ImageOff } from 'lucide-react';

import { useAttachmentObjectUrl } from './useAttachmentObjectUrl';

type AttachmentDto = Passenger.PassengerSupportAttachmentDto;

/** Human-readable size — kept coarse; nobody needs bytes in a chat bubble. */
export function formatBytes(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

/**
 * One image attachment. Its own component because the bytes are fetched through
 * the authenticated client (see {@link useAttachmentObjectUrl}) and a hook can't
 * be called from inside a `.map()`.
 */
function ImageAttachment({
  a,
  onView,
}: {
  a: AttachmentDto;
  onView: (a: AttachmentDto, src: string) => void;
}) {
  const { src, failed } = useAttachmentObjectUrl(a.url);

  if (failed) {
    return (
      <span className="flex items-center gap-1.5 text-xs opacity-75">
        <ImageOff size={14} className="shrink-0" />
        Couldn&apos;t load {a.name}
      </span>
    );
  }

  if (!src) {
    return (
      <div className="h-[120px] w-[200px] animate-pulse rounded-lg bg-black/10 dark:bg-white/10" />
    );
  }

  return (
    <button
      onClick={() => onView(a, src)}
      className="block overflow-hidden rounded-lg"
      aria-label={`View ${a.name}`}
    >
      {/* Capped: a tall screenshot would otherwise push the whole conversation
          off-screen. Plain <img>: the source is a blob: object URL, which
          next/image cannot optimize. */}
      {/* eslint-disable-next-line @next/next/no-img-element */}
      <img
        src={src}
        alt={a.name}
        className="max-h-[220px] max-w-[240px] cursor-zoom-in rounded-lg object-cover"
      />
    </button>
  );
}

/**
 * Attachments inside a message bubble: images as thumbnails, everything else as
 * a labelled file row. Non-images are not fetched until opened — pulling every
 * document in a thread just to draw a filename would be wasteful.
 */
export function MessageAttachments({
  attachments,
  mine,
  onViewImage,
  onOpenFile,
}: {
  attachments: AttachmentDto[];
  mine: boolean;
  onViewImage: (a: AttachmentDto, src: string) => void;
  onOpenFile: (a: AttachmentDto) => void;
}) {
  if (attachments.length === 0) return null;

  return (
    <div className="mt-1.5 space-y-1.5">
      {attachments.map((a) =>
        isSupportAttachmentImage(a.mimeType) ? (
          <ImageAttachment key={a.id} a={a} onView={onViewImage} />
        ) : (
          <button
            key={a.id}
            onClick={() => onOpenFile(a)}
            className={`flex w-full items-center gap-2 rounded-lg px-2 py-1.5 text-left transition ${
              mine
                ? 'bg-white/20 hover:bg-white/30'
                : 'border border-gray-200 bg-white hover:bg-gray-50 dark:border-slate-600 dark:bg-slate-700 dark:hover:bg-slate-600'
            }`}
          >
            <FileText size={16} className="shrink-0" />
            <span className="min-w-0">
              <span className="block truncate text-xs font-semibold">{a.name}</span>
              <span className="block text-[10px] opacity-75">{formatBytes(a.size)}</span>
            </span>
          </button>
        ),
      )}
    </div>
  );
}
