'use client';

import * as React from 'react';
import { Download, FileText, Loader2, Trash2 } from 'lucide-react';
import { useAuth } from '@/components/id/auth-provider';
import {
  attachmentDisplayName,
  attachmentFileExtension,
  inferAttachmentContentType,
  isImageAttachment,
  isPdfAttachment,
  type DocumentAttachmentMeta
} from '@/lib/document-attachments';
import { fetchDocumentPhotoUrl } from '@/lib/api';
import { resolveBrowserMediaUrl } from '@/lib/resilient-media-fetch';
import { cn } from '@/lib/utils';
import { DocumentAttachmentViewer, DocumentPhotoThumbnail } from './document-photo-viewer';

export type ResolvedDocumentAttachment = {
  storageKey: string;
  url: string;
  contentType: string;
  fileName: string;
};

interface DocumentPhotoGalleryProps {
  userId: string;
  token: string | null;
  storageKeys: string[];
  attachmentMeta?: Record<string, DocumentAttachmentMeta>;
  readOnly?: boolean;
  onRemove?: (storageKey: string) => void;
  layout?: 'grid' | 'strip';
  className?: string;
}

export function DocumentPhotoGallery({
  userId,
  token,
  storageKeys,
  attachmentMeta = {},
  readOnly,
  onRemove,
  layout = 'grid',
  className
}: DocumentPhotoGalleryProps) {
  const { isPinLocked } = useAuth();
  const [attachments, setAttachments] = React.useState<ResolvedDocumentAttachment[]>([]);
  const [loadingKeys, setLoadingKeys] = React.useState<Set<string>>(new Set());
  const [viewerOpen, setViewerOpen] = React.useState(false);
  const [viewerIndex, setViewerIndex] = React.useState(0);

  React.useEffect(() => {
    if (!token || storageKeys.length === 0 || isPinLocked) {
      setAttachments([]);
      return;
    }

    let cancelled = false;
    setLoadingKeys(new Set(storageKeys));
    void Promise.all(
      storageKeys.map(async (storageKey) => {
        const meta = attachmentMeta[storageKey];
        const contentType = inferAttachmentContentType(storageKey, meta);
        const fileName = attachmentDisplayName(storageKey, meta);
        try {
          const response = await fetchDocumentPhotoUrl(userId, storageKey, token, fileName);
          return {
            storageKey,
            accessUrl: resolveBrowserMediaUrl(response.accessUrl),
            contentType,
            fileName
          };
        } catch {
          return { storageKey, accessUrl: '', contentType, fileName };
        }
      })
    ).then((results) => {
      if (cancelled) return;
      setAttachments(
        results
          .filter((item) => Boolean(item.accessUrl))
          .map((item) => ({
            storageKey: item.storageKey,
            url: item.accessUrl,
            contentType: item.contentType,
            fileName: item.fileName
          }))
      );
      setLoadingKeys(new Set());
    });

    return () => {
      cancelled = true;
    };
  }, [attachmentMeta, isPinLocked, storageKeys.join('|'), token, userId]);

  function openViewer(storageKey: string) {
    const resolvedIndex = attachments.findIndex((item) => item.storageKey === storageKey);
    if (resolvedIndex >= 0) {
      setViewerIndex(resolvedIndex);
      setViewerOpen(true);
    }
  }

  if (storageKeys.length === 0) return null;

  const isStrip = layout === 'strip';

  return (
    <>
      <div
        className={cn(isStrip ? 'flex gap-2 overflow-x-auto pb-1' : 'grid grid-cols-2 gap-3', className)}
        onClick={(event) => event.stopPropagation()}
      >
        {storageKeys.map((storageKey) => {
          const meta = attachmentMeta[storageKey];
          const contentType = inferAttachmentContentType(storageKey, meta);
          const fileName = attachmentDisplayName(storageKey, meta);
          const resolved = attachments.find((item) => item.storageKey === storageKey);
          const loading = loadingKeys.has(storageKey);

          if (isImageAttachment(contentType)) {
            return (
              <div key={storageKey} className={cn('relative', isStrip && 'w-20 shrink-0')}>
                <DocumentPhotoThumbnail
                  url={resolved?.url}
                  loading={loading}
                  className={isStrip ? 'aspect-square rounded-xl' : undefined}
                  onClick={() => openViewer(storageKey)}
                />
                {!readOnly && onRemove ? (
                  <RemoveAttachmentButton storageKey={storageKey} onRemove={onRemove} />
                ) : null}
              </div>
            );
          }

          return (
            <div key={storageKey} className={cn('relative', isStrip && 'w-36 shrink-0')}>
              <button
                type="button"
                onClick={() => (resolved ? openViewer(storageKey) : undefined)}
                className={cn(
                  'flex h-full min-h-[96px] w-full flex-col items-start justify-between rounded-2xl border border-[#eceef4] bg-white p-3 text-left transition hover:border-[#20212b]',
                  isStrip && 'min-h-[80px]'
                )}
              >
                <div className="flex w-full items-start justify-between gap-2">
                  <div className="flex h-10 w-10 items-center justify-center rounded-xl bg-[#f4f5f8] text-[#667085]">
                    {loading ? <Loader2 className="h-4 w-4 animate-spin" /> : <FileText className="h-5 w-5" />}
                  </div>
                  <span className="rounded-lg bg-[#20212b] px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-white">
                    {attachmentFileExtension(contentType, fileName)}
                  </span>
                </div>
                <div className="mt-3 min-w-0">
                  <p className="truncate text-sm font-medium text-[#1f2430]">{fileName}</p>
                  <p className="mt-0.5 text-xs text-[#667085]">{isPdfAttachment(contentType) ? 'Открыть PDF' : 'Скачать файл'}</p>
                </div>
              </button>
              {resolved ? (
                <a
                  href={`${resolved.url}${resolved.url.includes('?') ? '&' : '?'}download=1`}
                  target="_blank"
                  rel="noreferrer"
                  className="absolute bottom-2 right-2 rounded-full bg-black/60 p-1.5 text-white hover:bg-black/80"
                  aria-label="Скачать файл"
                  onClick={(event) => event.stopPropagation()}
                >
                  <Download className="h-3.5 w-3.5" />
                </a>
              ) : null}
              {!readOnly && onRemove ? (
                <RemoveAttachmentButton storageKey={storageKey} onRemove={onRemove} className="right-2 top-2" />
              ) : null}
            </div>
          );
        })}
      </div>

      <DocumentAttachmentViewer
        open={viewerOpen}
        onOpenChange={setViewerOpen}
        initialIndex={viewerIndex}
        attachments={attachments}
      />
    </>
  );
}

function RemoveAttachmentButton({
  storageKey,
  onRemove,
  className
}: {
  storageKey: string;
  onRemove: (storageKey: string) => void;
  className?: string;
}) {
  return (
    <button
      type="button"
      onClick={(event) => {
        event.stopPropagation();
        onRemove(storageKey);
      }}
      className={cn('absolute right-2 top-2 rounded-full bg-black/60 p-1.5 text-white hover:bg-black/80', className)}
      aria-label="Удалить файл"
    >
      <Trash2 className="h-3.5 w-3.5" />
    </button>
  );
}

interface DocumentPhotosInlineProps {
  userId: string;
  token: string | null;
  storageKeys: string[];
  attachmentMeta?: Record<string, DocumentAttachmentMeta>;
  className?: string;
}

/** Горизонтальная полоска файлов документа для списков. */
export function DocumentPhotosInline({ userId, token, storageKeys, attachmentMeta, className }: DocumentPhotosInlineProps) {
  if (!storageKeys.length) return null;
  return (
    <DocumentPhotoGallery
      userId={userId}
      token={token}
      storageKeys={storageKeys}
      attachmentMeta={attachmentMeta}
      readOnly
      layout="strip"
      className={className}
    />
  );
}
