import { useMemo, useState } from 'react';

import type {
  ConversationAttachmentIndex,
  ConversationAttachmentItem,
} from '../lib/conversationFeatures';
import { AttachmentGeneric } from './AttachmentGeneric';
import { AttachmentImage } from './AttachmentImage';
import { ArrowRightIcon, FileIcon, ImageIcon, MicIcon, VideoIcon, XIcon } from './icons';

type DrawerTab = 'media' | 'files' | 'audio';

interface Props {
  open: boolean;
  index: ConversationAttachmentIndex;
  senderNameFor: (senderId: string) => string;
  onJumpToMessage: (messageId: string) => void;
  onClose: () => void;
}

const TAB_LABELS: Record<DrawerTab, string> = {
  media: 'Medien',
  files: 'Dateien',
  audio: 'Audio',
};

export function MediaFilesDrawer({ open, index, senderNameFor, onJumpToMessage, onClose }: Props) {
  const [tab, setTab] = useState<DrawerTab>('media');
  const items = index[tab];

  if (!open) return null;

  return (
    <aside className="flex w-[380px] shrink-0 flex-col border-l border-line bg-surface-2 dark:bg-[#2b2d31]">
      <header className="flex min-h-[65px] items-center gap-3 border-b border-line px-4">
        <div className="flex h-10 w-10 items-center justify-center rounded-xl bg-accent/10 text-accent">
          <ImageIcon className="h-5 w-5" />
        </div>
        <div className="min-w-0 flex-1">
          <p className="truncate font-display text-base font-semibold text-fg">Medien & Dateien</p>
          <p className="text-xs text-fg-muted">{index.all.length} Elemente im geladenen Verlauf</p>
        </div>
        <button
          type="button"
          onClick={onClose}
          aria-label="Drawer schließen"
          title="Drawer schließen"
          className="flex h-9 w-9 cursor-pointer items-center justify-center rounded-lg text-fg-muted transition hover:bg-surface-3 hover:text-fg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 dark:hover:bg-[#383a40]"
        >
          <XIcon className="h-4 w-4" />
        </button>
      </header>

      <div className="grid grid-cols-3 gap-1 border-b border-line p-2">
        {(['media', 'files', 'audio'] as DrawerTab[]).map((item) => (
          <button
            key={item}
            type="button"
            onClick={() => setTab(item)}
            className={
              'cursor-pointer rounded-lg px-2 py-2 text-xs font-semibold transition focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 ' +
              (tab === item
                ? 'bg-accent text-accent-fg'
                : 'text-fg-muted hover:bg-surface-3 hover:text-fg dark:hover:bg-[#383a40]')
            }
          >
            {TAB_LABELS[item]} · {index[item].length}
          </button>
        ))}
      </div>

      <div className="min-h-0 flex-1 overflow-y-auto p-3">
        {items.length === 0 ? (
          <EmptyState tab={tab} />
        ) : tab === 'media' ? (
          <div className="grid grid-cols-2 gap-2">
            {items.map((item) => (
              <MediaTile
                key={item.handle.id}
                item={item}
                senderName={senderNameFor(item.senderId)}
                onJumpToMessage={onJumpToMessage}
              />
            ))}
          </div>
        ) : (
          <div className="space-y-2">
            {items.map((item) => (
              <FileRow
                key={item.handle.id}
                item={item}
                senderName={senderNameFor(item.senderId)}
                onJumpToMessage={onJumpToMessage}
              />
            ))}
          </div>
        )}
      </div>
    </aside>
  );
}

function MediaTile({
  item,
  senderName,
  onJumpToMessage,
}: {
  item: ConversationAttachmentItem;
  senderName: string;
  onJumpToMessage: (messageId: string) => void;
}) {
  const isImage = item.handle.mimeType.startsWith('image/');
  const isVideo = item.handle.mimeType.startsWith('video/');
  return (
    <article className="overflow-hidden rounded-lg border border-line bg-surface-3 dark:bg-[#313338]">
      <div className="flex aspect-square items-center justify-center overflow-hidden bg-black/20">
        {isImage ? (
          <div className="flex max-h-full max-w-full items-center justify-center p-1 [&_button]:m-0 [&_img]:max-h-36">
            <AttachmentImage handle={item.handle} />
          </div>
        ) : isVideo ? (
          <div className="flex flex-col items-center gap-2 text-fg-muted">
            <VideoIcon className="h-7 w-7" />
            <span className="text-xs">Video</span>
          </div>
        ) : (
          <ImageIcon className="h-7 w-7 text-fg-muted" />
        )}
      </div>
      <AttachmentMeta item={item} senderName={senderName} onJumpToMessage={onJumpToMessage} />
    </article>
  );
}

function FileRow({
  item,
  senderName,
  onJumpToMessage,
}: {
  item: ConversationAttachmentItem;
  senderName: string;
  onJumpToMessage: (messageId: string) => void;
}) {
  const isAudio = item.handle.mimeType.startsWith('audio/');
  return (
    <article className="rounded-lg border border-line bg-surface-3 p-2 dark:bg-[#313338]">
      <div className="flex items-center gap-2">
        <span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-accent/10 text-accent">
          {isAudio ? <MicIcon className="h-5 w-5" /> : <FileIcon className="h-5 w-5" />}
        </span>
        <div className="min-w-0 flex-1">
          <p className="truncate text-sm font-semibold text-fg">{labelFor(item.handle.mimeType)}</p>
          <p className="truncate text-xs text-fg-muted">
            {formatSize(item.handle.sizeBytes)} · {senderName}
          </p>
        </div>
      </div>
      {!isAudio && <AttachmentGeneric handle={item.handle} />}
      <AttachmentMeta
        item={item}
        senderName={senderName}
        onJumpToMessage={onJumpToMessage}
        compact
      />
    </article>
  );
}

function AttachmentMeta({
  item,
  senderName,
  onJumpToMessage,
  compact = false,
}: {
  item: ConversationAttachmentItem;
  senderName: string;
  onJumpToMessage: (messageId: string) => void;
  compact?: boolean;
}) {
  const date = useMemo(
    () =>
      new Intl.DateTimeFormat(undefined, {
        day: '2-digit',
        month: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
      }).format(new Date(item.createdAt)),
    [item.createdAt],
  );
  return (
    <div className={(compact ? 'pt-2' : 'p-2') + ' flex items-center gap-2'}>
      <div className="min-w-0 flex-1">
        {!compact && <p className="truncate text-xs font-semibold text-fg">{senderName}</p>}
        <p className="truncate text-[11px] text-fg-muted">{date}</p>
      </div>
      <button
        type="button"
        onClick={() => onJumpToMessage(item.messageId)}
        aria-label="Zur Nachricht springen"
        title="Zur Nachricht springen"
        className="flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-lg text-fg-muted transition hover:bg-surface-2 hover:text-fg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 dark:hover:bg-[#383a40]"
      >
        <ArrowRightIcon className="h-4 w-4" />
      </button>
    </div>
  );
}

function EmptyState({ tab }: { tab: DrawerTab }) {
  const Icon = tab === 'media' ? ImageIcon : tab === 'audio' ? MicIcon : FileIcon;
  return (
    <div className="flex h-full min-h-[280px] flex-col items-center justify-center gap-3 text-center text-fg-muted">
      <span className="flex h-12 w-12 items-center justify-center rounded-xl bg-surface-3 dark:bg-[#313338]">
        <Icon className="h-6 w-6" />
      </span>
      <p className="max-w-48 text-sm">
        Noch keine {TAB_LABELS[tab].toLowerCase()} im geladenen Verlauf.
      </p>
    </div>
  );
}

function labelFor(mimeType: string): string {
  if (mimeType.startsWith('audio/')) return 'Audiodatei';
  if (mimeType === 'application/pdf') return 'PDF-Datei';
  if (mimeType.startsWith('text/')) return 'Textdatei';
  return mimeType || 'Datei';
}

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';
}
