import { useMemo, useState } from 'react';
import { FileIcon, Globe, Loader2, Plus, X } from 'lucide-react';
import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area';
import { Skeleton } from '@/components/ui/skeleton';
import { cn } from '@/lib/utils';
import type { LinkPreviewEntry } from '@/hooks/use-link-metadata';
import { domainFromUrl } from '@/lib/link-metadata';
import {
  AttachmentLightbox,
  getAttachmentHandler,
  type AttachmentItem,
} from '@/features/attachments/attachment-lightbox';
import { platform } from '@/lib/platform';

export interface PendingAttachment {
  id: string;
  file: File;
  thumbnailUrl?: string;
  status: 'pending' | 'uploading' | 'uploaded' | 'error';
}

interface AttachmentStripProps {
  attachments: PendingAttachment[];
  onRemove: (id: string) => void;
  onAddClick: () => void;
  linkPreviews?: LinkPreviewEntry[];
}

function pendingToItem(p: PendingAttachment): AttachmentItem {
  return {
    id: p.id,
    filename: p.file.name,
    mimeType: p.file.type || 'application/octet-stream',
    sizeBytes: p.file.size,
    source: { kind: 'local', file: p.file },
  };
}

function formatFileSize(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

function AttachmentThumbnail({
  attachment,
  onRemove,
  onPreview,
}: {
  attachment: PendingAttachment;
  onRemove: () => void;
  onPreview?: () => void;
}) {
  const isImage = attachment.file.type.startsWith('image/');
  const isUploading = attachment.status === 'uploading';
  const isError = attachment.status === 'error';
  const previewable = getAttachmentHandler(attachment.file.type) === 'lightbox';

  return (
    <div
      role={previewable ? 'button' : undefined}
      tabIndex={previewable ? 0 : undefined}
      onClick={previewable && onPreview ? onPreview : undefined}
      className={cn(
        'group relative flex h-16 w-16 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-white/10',
        previewable && 'cursor-pointer',
        isError && 'ring-1 ring-red-400/50',
      )}
    >
      {isImage && attachment.thumbnailUrl ? (
        <img
          src={attachment.thumbnailUrl}
          alt={attachment.file.name}
          className="h-full w-full object-cover"
        />
      ) : (
        <div className="flex flex-col items-center gap-0.5 px-1">
          <FileIcon className="size-5 text-white/60" />
          <span className="max-w-full truncate text-[9px] text-white/50">
            {attachment.file.name}
          </span>
          <span className="text-[9px] text-white/40">
            {formatFileSize(attachment.file.size)}
          </span>
        </div>
      )}

      {isUploading && (
        <div className="absolute inset-0 flex items-center justify-center bg-black/50">
          <Loader2 className="size-4 animate-spin text-white/70" />
        </div>
      )}

      <button
        type="button"
        onClick={(e) => {
          e.stopPropagation();
          onRemove();
        }}
        className="absolute right-0.5 top-0.5 hidden rounded-full bg-black/70 p-0.5 text-white/70 hover:text-white group-hover:block"
      >
        <X className="size-3" />
      </button>
    </div>
  );
}

function LinkPreviewThumbnail({ entry }: { entry: LinkPreviewEntry }) {
  if (entry.isLoading) {
    return (
      <div className="flex h-16 w-28 shrink-0 flex-col gap-1.5 rounded-lg bg-white/10 p-2">
        <Skeleton className="h-2 w-16 bg-white/10" />
        <Skeleton className="h-3 w-24 bg-white/10" />
      </div>
    );
  }

  // Metadata fetch can fail; fall back to the bare URL so the link stays usable.
  const { metadata } = entry;
  const domain = metadata?.domain ?? domainFromUrl(entry.url);
  const title = metadata?.title ?? entry.url;

  return (
    <button
      type="button"
      onClick={() => platform.link.openExternal(metadata?.url ?? entry.url)}
      className="flex h-16 w-28 shrink-0 flex-col justify-center gap-1 overflow-hidden rounded-lg bg-white/10 px-2 py-1.5 text-left transition-colors hover:bg-white/15"
    >
      <div className="flex items-center gap-1 text-[10px] text-white/40">
        {metadata?.favicon ? (
          <img
            src={metadata.favicon}
            alt=""
            className="size-3 rounded-sm"
            onError={(e) => {
              (e.target as HTMLImageElement).style.display = 'none';
            }}
          />
        ) : (
          <Globe className="size-3" />
        )}
        <span className="truncate">{domain}</span>
      </div>
      {title && (
        <p className="line-clamp-2 text-[11px] font-medium leading-tight text-white/80">
          {title}
        </p>
      )}
    </button>
  );
}

export function AttachmentStrip({
  attachments,
  onRemove,
  onAddClick,
  linkPreviews,
}: AttachmentStripProps) {
  const hasLinks = linkPreviews && linkPreviews.length > 0;

  // Lightbox state — only previewable attachments go in.
  const previewable = useMemo(
    () =>
      attachments.filter(
        (a) => getAttachmentHandler(a.file.type) === 'lightbox',
      ),
    [attachments],
  );
  const items = useMemo(() => previewable.map(pendingToItem), [previewable]);
  const [openIndex, setOpenIndex] = useState<number | null>(null);

  if (attachments.length === 0 && !hasLinks) return null;

  return (
    <>
      <ScrollArea className="w-full">
        <div className="flex items-center gap-2 py-2">
          {attachments.map((a) => (
            <AttachmentThumbnail
              key={a.id}
              attachment={a}
              onRemove={() => onRemove(a.id)}
              onPreview={() => {
                const idx = previewable.indexOf(a);
                if (idx >= 0) setOpenIndex(idx);
              }}
            />
          ))}

          {linkPreviews?.map((entry) => (
            <LinkPreviewThumbnail key={entry.url} entry={entry} />
          ))}

          <button
            type="button"
            onClick={(e) => {
              e.stopPropagation();
              onAddClick();
            }}
            className="flex h-16 w-16 shrink-0 items-center justify-center rounded-lg border border-dashed border-white/20 text-white/40 transition-colors hover:border-white/40 hover:text-white/60"
          >
            <Plus className="size-5" />
          </button>
        </div>
        <ScrollBar orientation="horizontal" />
      </ScrollArea>

      {items.length > 0 && (
        <AttachmentLightbox
          items={items}
          openIndex={openIndex}
          onOpenChange={setOpenIndex}
          onRemove={(item) => onRemove(item.id)}
        />
      )}
    </>
  );
}
