import { type AttachmentHandle, downloadAndDecryptAttachment } from '@chat-app/shared/chat';
import { useEffect, useState } from 'react';

import { getCachedAttachment, putCachedAttachment } from '../lib/attachmentCache';
import { supabase } from '../lib/supabase';
import { AlertIcon, SpinnerIcon } from './icons';

interface Props {
  handle: AttachmentHandle;
}

// PDF preview rendered via the browser's built-in PDF viewer (Chromium /
// Safari both ship one). Embedding via <object> with a fallback link keeps
// the implementation tiny — no pdf.js dependency.
export function AttachmentPdf({ handle }: Props) {
  const [blobUrl, setBlobUrl] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [expanded, setExpanded] = useState(false);

  useEffect(() => {
    let cancelled = false;
    let url: string | null = null;
    setError(null);
    setBlobUrl(null);

    void (async () => {
      const cached = await getCachedAttachment(handle.id);
      if (cached) {
        if (cancelled) return;
        const typed = new Blob([cached], { type: 'application/pdf' });
        url = URL.createObjectURL(typed);
        setBlobUrl(url);
        return;
      }
      try {
        const blob = await downloadAndDecryptAttachment({ client: supabase, handle });
        if (cancelled) return;
        // Force the application/pdf type so the browser plugin engages.
        const typed = new Blob([blob], { type: 'application/pdf' });
        url = URL.createObjectURL(typed);
        setBlobUrl(url);
        void putCachedAttachment(handle.id, blob);
      } catch (err: unknown) {
        if (!cancelled) {
          setError(err instanceof Error ? err.message : 'download failed');
        }
      }
    })();

    return () => {
      cancelled = true;
      if (url) URL.revokeObjectURL(url);
    };
  }, [handle.id, handle.storagePath, handle.keyB64, handle.nonceB64]);

  if (error) {
    return (
      <div className="mt-2 inline-flex items-center gap-2 rounded-lg border border-rose-500/20 bg-rose-500/10 px-3 py-2 text-xs text-rose-200">
        <AlertIcon className="h-4 w-4" />
        <span>{error}</span>
      </div>
    );
  }

  if (!blobUrl) {
    return (
      <div className="mt-2 flex h-24 w-[320px] items-center justify-center rounded-lg border border-line bg-surface-2 text-fg-muted">
        <SpinnerIcon className="h-5 w-5" />
      </div>
    );
  }

  return (
    <div className="mt-2 w-full max-w-[420px] overflow-hidden rounded-lg border border-line bg-surface-2">
      <div className="flex items-center justify-between gap-2 border-b border-line bg-surface-3 px-3 py-2 text-xs">
        <span className="flex items-center gap-2 truncate text-fg">
          <PdfGlyph />
          <span className="truncate">PDF · {formatSize(handle.sizeBytes)}</span>
        </span>
        <div className="flex gap-1">
          <button
            type="button"
            onClick={() => setExpanded((v) => !v)}
            className="cursor-pointer rounded-md border border-line bg-surface-2 px-2 py-0.5 text-[11px] text-fg hover:bg-surface-3"
          >
            {expanded ? 'Einklappen' : 'Vorschau'}
          </button>
          <a
            href={blobUrl}
            download={'attachment-' + handle.id.slice(0, 8) + '.pdf'}
            className="cursor-pointer rounded-md border border-line bg-surface-2 px-2 py-0.5 text-[11px] text-fg no-underline hover:bg-surface-3"
          >
            Download
          </a>
        </div>
      </div>
      {expanded && (
        <object data={blobUrl} type="application/pdf" className="block h-[420px] w-full">
          <p className="p-4 text-xs text-fg-muted">
            Vorschau nicht verfügbar — bitte herunterladen.
          </p>
        </object>
      )}
    </div>
  );
}

function PdfGlyph() {
  return (
    <svg viewBox="0 0 16 16" width="14" height="14" fill="currentColor" aria-hidden="true">
      <path d="M3 2a1 1 0 011-1h6l3 3v10a1 1 0 01-1 1H4a1 1 0 01-1-1V2zm7 0v3h3l-3-3zM5 9h6v1H5V9zm0 2h6v1H5v-1zm0-4h2v1H5V7z" />
    </svg>
  );
}

function formatSize(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';
}
