import React, { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { Archive, Maximize2, Minimize2, Pin, RefreshCw, Sparkles } from 'lucide-react';
import { researchBridge } from '../../lib/researchBridge';
import type {
  GhostNote,
  GhostRecommendedAction,
  GhostResolutionStatus,
  NoteEmbedInput,
  NoteAuditTrail,
  NoteType,
  ResearchFile,
  ResearchNote,
  ThesisStatus,
  UploadResearchFileInput,
} from '../../types/research';
import {
  ConfidenceBadge,
  EvidenceBadge,
  FreshnessBadge,
  NoteTypeBadge,
  TagChip,
} from './primitives/Badges';
import { GHOST_CLASS_LABELS, NOTE_TYPE_LABELS } from './primitives/researchMeta';
import { ResearchEditor } from './primitives/ResearchEditor';
import {
  filterResearchFilesByIds,
  ResearchFileList,
  ResearchFilePickerModal,
  ResearchFileUploadButton,
} from './primitives/ResearchFiles';

interface ResearchInspectorPaneProps {
  note: ResearchNote | null;
  ghost: GhostNote | null;
  hiddenMessage?: string | null;
  auditTrail: NoteAuditTrail | null;
  isLoadingAuditTrail: boolean;
  isUpdatingNote?: boolean;
  isArchivingNote?: boolean;
  isPromotingNote?: boolean;
  isReviewingGhost?: boolean;
  error?: string | null;
  onSelectNote?: (noteId: string) => void;
  onRefreshAuditTrail: () => void;
  onUpdateNote: (noteId: string, patch: {
    rawText?: string;
    bodyHtml?: string;
    embeds?: NoteEmbedInput[];
    fileIds?: string[];
    title?: string;
    noteType?: NoteType;
    pinned?: boolean;
    thesisStatus?: ThesisStatus;
  }) => Promise<unknown>;
  onArchiveNote: (noteId: string, archived: boolean) => Promise<unknown>;
  onPromoteNote: (noteId: string, thesisStatus?: ThesisStatus, noteType?: NoteType) => Promise<unknown>;
  onReviewGhost: (ghostId: string, action: 'accept' | 'ignore' | 'dismiss' | 'pin') => Promise<unknown>;
  onResolveGhost: (
    ghostId: string,
    resolutionStatus: GhostResolutionStatus,
    actionTaken?: GhostRecommendedAction,
  ) => Promise<unknown>;
  workspaceFiles?: ResearchFile[];
  onUploadFiles?: (files: UploadResearchFileInput[]) => Promise<ResearchFile[] | unknown>;
  onOpenFile?: (file: ResearchFile) => Promise<void> | void;
  onPreviewFile?: (file: ResearchFile) => void;
}

const editableNoteTypes: NoteType[] = [
  'fact',
  'management_signal',
  'claim',
  'thesis',
  'sub_thesis',
  'risk',
  'catalyst',
  'valuation_point',
  'question',
  'contradiction',
  'channel_check',
  'mosaic_insight',
];

const labelize = (value: string) =>
  value
    .split('_')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(' ');

const leverageLabel = (score?: number) => {
  if ((score ?? 0) >= 0.78) {
    return 'High leverage';
  }
  if ((score ?? 0) >= 0.55) {
    return 'Medium leverage';
  }
  return 'Low leverage';
};

export const ResearchInspectorPane: React.FC<ResearchInspectorPaneProps> = ({
  note,
  ghost,
  hiddenMessage,
  auditTrail,
  isLoadingAuditTrail,
  isUpdatingNote = false,
  isArchivingNote = false,
  isPromotingNote = false,
  isReviewingGhost = false,
  error,
  onSelectNote,
  onRefreshAuditTrail,
  onUpdateNote,
  onArchiveNote,
  onPromoteNote,
  onReviewGhost,
  onResolveGhost,
  workspaceFiles = [],
  onUploadFiles,
  onOpenFile,
  onPreviewFile,
}) => {
  const [draftTitle, setDraftTitle] = useState('');
  const [draftBody, setDraftBody] = useState('');
  const [draftBodyHtml, setDraftBodyHtml] = useState('');
  const [draftEmbeds, setDraftEmbeds] = useState<NoteEmbedInput[]>([]);
  const [draftFileIds, setDraftFileIds] = useState<string[]>([]);
  const [draftType, setDraftType] = useState<NoteType>('claim');
  const [isEditorFullscreen, setIsEditorFullscreen] = useState(false);
  const [isFilePickerOpen, setIsFilePickerOpen] = useState(false);
  const [fileError, setFileError] = useState<string | null>(null);

  useEffect(() => {
    if (!note) {
      return;
    }

    setDraftTitle(note.title ?? '');
    setDraftBody(note.rawText);
    setDraftBodyHtml(note.bodyHtml ?? note.rawText);
    setDraftEmbeds(note.embeds ?? []);
    setDraftFileIds(note.fileIds ?? []);
    setDraftType(note.noteType);
  }, [note]);

  useEffect(() => {
    if (!isEditorFullscreen) return;
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') setIsEditorFullscreen(false);
    };
    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [isEditorFullscreen]);

  if (!note && !ghost) {
    return (
      <div className="flex h-full flex-col justify-between p-4 sm:p-5">
        <div>
          <h2 className="text-base font-semibold text-[var(--research-text-strong)] sm:text-lg">
            Inspector
          </h2>
          <p className="mt-2 text-xs leading-6 text-[var(--research-text-muted)] sm:mt-2.5 sm:text-sm">
            Select a note or ghost note to inspect provenance, links, evidence, and promotion controls.
          </p>
        </div>
      </div>
    );
  }

  return (
    <div className="space-y-4 p-4 sm:space-y-5 sm:p-5">
      {hiddenMessage ? (
        <div className="rounded-2xl border border-warn/40 bg-warn/10 px-3 py-2 text-xs text-warn">
          {hiddenMessage}
        </div>
      ) : null}
      {error ? (
        <div className="rounded-2xl border border-negative/40 bg-negative/10 px-3 py-2 text-xs text-negative">
          {error}
        </div>
      ) : null}

      {ghost ? (
        <>
          <div>
            <div className="text-[10px] uppercase tracking-[0.2em] text-term-text-tertiary">
              Conviction Intervention
            </div>
            <h2 className="mt-2 text-lg font-semibold text-term-text sm:text-xl">
              {ghost.headline}
            </h2>
          </div>

          <div className="flex flex-wrap gap-2">
            <TagChip label={GHOST_CLASS_LABELS[ghost.ghostClass]} />
            <TagChip label={leverageLabel(ghost.leverageScore)} />
            <TagChip label={`Support: ${labelize(ghost.supportStrength ?? (ghost.evidenceThresholdMet ? 'strong' : 'none'))}`} />
            <TagChip label={`Status: ${labelize(ghost.resolutionStatus ?? 'open')}`} />
            <ConfidenceBadge confidence={ghost.confidence} />
            <FreshnessBadge timestamp={ghost.updatedAt} />
          </div>

          <div className="space-y-3">
            <section className="rounded-2xl border border-term-border bg-term-bg p-3">
              <div className="text-[10px] uppercase tracking-[0.18em] text-term-text-tertiary">
                Targeted Point
              </div>
              <p className="mt-2 text-sm leading-6 text-term-text">
                {ghost.targetClaimText || ghost.body}
              </p>
              {ghost.targetNoteId && onSelectNote ? (
                <button
                  type="button"
                  onClick={() => onSelectNote(ghost.targetNoteId!)}
                  className="mt-2 text-xs text-info underline decoration-info/40 underline-offset-2 hover:text-term-text"
                >
                  View targeted note
                </button>
              ) : null}
            </section>

            <section className="rounded-2xl border border-term-border bg-term-bg p-3">
              <div className="text-[10px] uppercase tracking-[0.18em] text-term-text-tertiary">
                Why It Matters
              </div>
              <p className="mt-2 text-sm leading-6 text-term-text-muted">
                {ghost.whyItMatters || 'This point may affect the research case and should be resolved before it becomes accepted support.'}
              </p>
            </section>

            <section className="rounded-2xl border border-term-border bg-term-bg p-3">
              <div className="text-[10px] uppercase tracking-[0.18em] text-term-text-tertiary">
                Current Support
              </div>
              <p className="mt-2 text-sm leading-6 text-term-text-muted">
                {ghost.currentSupportSummary ||
                  `${ghost.supportingNoteIds.length} supporting note(s), ${ghost.contradictingNoteIds.length} contradicting note(s), ${ghost.sourceIds.length} source(s).`}
              </p>
            </section>

            <section className="rounded-2xl border border-warn/40 bg-warn/10 p-3">
              <div className="text-[10px] uppercase tracking-[0.18em] text-warn">
                Counter-Case
              </div>
              <p className="mt-2 text-sm leading-6 text-term-text">
                {ghost.counterCase || ghost.body}
              </p>
            </section>

            <section className="rounded-2xl border border-info/30 bg-info/5 p-3">
              <div className="text-[10px] uppercase tracking-[0.18em] text-term-text-tertiary">
                Recommended Next Move
              </div>
              <p className="mt-2 text-sm font-medium text-term-text">
                {labelize(ghost.recommendedAction ?? 'find_primary_source')}
              </p>
              <p className="mt-1 text-sm leading-6 text-term-text-muted">
                {ghost.recommendedActionRationale ||
                  'Add, link, or revise the evidence needed to decide whether this point should increase conviction.'}
              </p>
            </section>
          </div>

          <div className="grid gap-2.5 sm:gap-3">
            <button
              type="button"
              disabled={isReviewingGhost}
              onClick={() => {
                void onResolveGhost(ghost.id, 'in_progress', ghost.recommendedAction);
              }}
              className="w-full rounded-2xl border border-info/40 bg-info/10 px-4 py-2.5 text-sm text-info transition-colors hover:border-info hover:text-term-text disabled:cursor-not-allowed disabled:opacity-50 sm:py-3"
            >
              Mark in progress
            </button>
            <button
              type="button"
              disabled={isReviewingGhost}
              onClick={() => {
                void onResolveGhost(ghost.id, 'strengthened', ghost.recommendedAction);
              }}
              className="w-full rounded-2xl border border-term-border bg-term-surface px-4 py-2.5 text-sm text-term-text transition-colors hover:border-info/50 disabled:cursor-not-allowed disabled:opacity-50 sm:py-3"
            >
              Mark strengthened
            </button>
            <button
              type="button"
              disabled={isReviewingGhost}
              onClick={() => {
                void onResolveGhost(ghost.id, 'weakened', 'downgrade_to_inference');
              }}
              className="w-full rounded-2xl border border-term-border bg-term-surface px-4 py-2.5 text-sm text-term-text transition-colors hover:border-info/50 disabled:cursor-not-allowed disabled:opacity-50 sm:py-3"
            >
              Downgrade conviction
            </button>
            <button
              type="button"
              disabled={isReviewingGhost}
              onClick={() => {
                void onResolveGhost(ghost.id, 'waived', 'mark_waived');
              }}
              className="w-full rounded-2xl border border-warn/40 bg-warn/10 px-4 py-2.5 text-sm text-warn transition-colors hover:border-warn/70 disabled:cursor-not-allowed disabled:opacity-50 sm:py-3"
            >
              Mark waived
            </button>
            <button
              type="button"
              disabled={isReviewingGhost}
              onClick={() => {
                void onReviewGhost(ghost.id, 'dismiss');
              }}
              className="w-full rounded-2xl border border-negative/40 bg-negative/10 px-4 py-2.5 text-sm text-negative transition-colors hover:border-negative/70 disabled:cursor-not-allowed disabled:opacity-50 sm:py-3"
            >
              Dismiss ghost
            </button>
          </div>
        </>
      ) : null}

      {note ? (
        <>
          <div className="flex flex-wrap items-center gap-2">
            <NoteTypeBadge noteType={note.noteType} />
            <EvidenceBadge status={note.evidenceStatus} />
            <ConfidenceBadge confidence={note.confidence} />
            <FreshnessBadge timestamp={note.updatedAt} />
          </div>

          <div className="space-y-3">
            <label className="flex flex-col gap-2">
              <span className="text-[10px] uppercase tracking-[0.18em] text-term-text-tertiary">
                Title
              </span>
              <input
                value={draftTitle}
                onChange={(event) => setDraftTitle(event.target.value)}
                className="w-full rounded-2xl border border-term-border bg-term-bg px-3 py-2.5 text-sm text-term-text outline-none transition-colors focus:border-info sm:py-3"
              />
            </label>
            <label className="flex flex-col gap-2">
              <div className="flex items-center justify-between">
                <span className="text-[10px] uppercase tracking-[0.18em] text-term-text-tertiary">
                  Body
                </span>
                <button
                  type="button"
                  onClick={() => setIsEditorFullscreen(true)}
                  className="inline-flex items-center gap-1 rounded-lg border border-term-border bg-term-surface px-1.5 py-1 text-term-text-tertiary transition-colors hover:border-info/60 hover:text-term-text"
                  aria-label="Expand editor"
                >
                  <Maximize2 className="h-3 w-3" />
                </button>
              </div>
              {!isEditorFullscreen && (
                <ResearchEditor
                  content={draftBodyHtml}
                  embeds={draftEmbeds}
                  minRows={6}
                  className="rounded-2xl"
                  onPreviewLink={async (url) => {
                    const result = await researchBridge.previewNoteLink({ url, kind: 'article' });
                    return result.embed;
                  }}
                  onChange={(html, text, embeds) => {
                    setDraftBodyHtml(html);
                    setDraftBody(text);
                    setDraftEmbeds(embeds);
                  }}
                />
              )}
            </label>
            <label className="flex flex-col gap-2">
              <span className="text-[10px] uppercase tracking-[0.18em] text-term-text-tertiary">
                Note Type
              </span>
              <select
                value={draftType}
                onChange={(event) => setDraftType(event.target.value as NoteType)}
                className="w-full rounded-2xl border border-term-border bg-term-bg px-3 py-2.5 text-sm text-term-text outline-none transition-colors focus:border-info sm:py-3"
              >
                {editableNoteTypes.map((noteType) => (
                  <option key={noteType} value={noteType}>
                    {NOTE_TYPE_LABELS[noteType]}
                  </option>
                ))}
              </select>
            </label>
            <div className="grid grid-cols-2 gap-2.5 sm:gap-3">
              <button
                type="button"
                disabled={isUpdatingNote}
                onClick={() => {
                  void onUpdateNote(note.id, {
                    title: draftTitle,
                    rawText: draftBody,
                    bodyHtml: draftBodyHtml,
                    embeds: draftEmbeds,
                    fileIds: draftFileIds,
                    noteType: draftType,
                  });
                }}
                className="rounded-2xl border border-info/40 bg-info/10 px-3 py-2.5 text-sm text-info transition-colors hover:border-info hover:text-term-text disabled:cursor-not-allowed disabled:opacity-50 sm:px-4 sm:py-3"
              >
                {isUpdatingNote ? 'Saving...' : 'Save note'}
              </button>
              <button
                type="button"
                disabled={isPromotingNote}
                onClick={() => {
                  void onPromoteNote(
                    note.id,
                    'accepted_core',
                    note.noteType === 'thesis' ? 'thesis' : 'sub_thesis',
                  );
                }}
                className="inline-flex items-center justify-center gap-1.5 rounded-2xl border border-positive/35 bg-positive/10 px-3 py-2.5 text-sm text-positive transition-colors hover:border-positive/60 disabled:cursor-not-allowed disabled:opacity-50 sm:gap-2 sm:px-4 sm:py-3"
              >
                <Sparkles className="h-3.5 w-3.5 sm:h-4 sm:w-4" />
                {isPromotingNote ? 'Promoting...' : 'Promote'}
              </button>
            </div>
            <div className="grid grid-cols-2 gap-2.5 sm:gap-3">
              <button
                type="button"
                disabled={isUpdatingNote}
                onClick={() => {
                  void onUpdateNote(note.id, { pinned: !note.pinned });
                }}
                className="inline-flex items-center justify-center gap-1.5 rounded-2xl border border-term-border bg-term-surface px-3 py-2.5 text-sm text-term-text transition-colors hover:border-info/50 disabled:cursor-not-allowed disabled:opacity-50 sm:gap-2 sm:px-4 sm:py-3"
              >
                <Pin className="h-3.5 w-3.5 sm:h-4 sm:w-4" />
                {note.pinned ? 'Unpin' : 'Pin'}
              </button>
              <button
                type="button"
                disabled={isArchivingNote}
                onClick={() => {
                  void onArchiveNote(note.id, !note.archived);
                }}
                className="inline-flex items-center justify-center gap-1.5 rounded-2xl border border-negative/40 bg-negative/10 px-3 py-2.5 text-sm text-negative transition-colors hover:border-negative/70 disabled:cursor-not-allowed disabled:opacity-50 sm:gap-2 sm:px-4 sm:py-3"
              >
                <Archive className="h-3.5 w-3.5 sm:h-4 sm:w-4" />
                {isArchivingNote ? 'Saving...' : note.archived ? 'Restore' : 'Archive'}
              </button>
            </div>
          </div>

          <div className="space-y-3 rounded-2xl border border-term-border bg-term-surface p-3 sm:p-4">
            <div className="flex flex-wrap items-center justify-between gap-2">
              <div className="text-[10px] uppercase tracking-[0.18em] text-term-text-tertiary">
                Attached Files
              </div>
              <div className="flex flex-wrap gap-2">
                {onUploadFiles ? (
                  <ResearchFileUploadButton
                    label="Upload"
                    onError={setFileError}
                    onUpload={async (files) => {
                      setFileError(null);
                      const uploaded = await onUploadFiles(files);
                      const uploadedIds = Array.isArray(uploaded)
                        ? uploaded.map((file) => file.id)
                        : [];
                      setDraftFileIds((current) =>
                        Array.from(new Set([...current, ...uploadedIds])),
                      );
                    }}
                  />
                ) : null}
                <button
                  type="button"
                  onClick={() => setIsFilePickerOpen(true)}
                  className="rounded-xl border border-term-border bg-term-bg px-3 py-2 text-xs uppercase tracking-[0.16em] text-term-text-tertiary transition-colors hover:border-info/60 hover:text-term-text"
                >
                  Link Existing
                </button>
              </div>
            </div>
            <ResearchFileList
              files={filterResearchFilesByIds(workspaceFiles, draftFileIds)}
              selectedFileIds={draftFileIds}
              emptyLabel="No attached files"
              compact
              onOpenFile={onOpenFile}
              onPreviewFile={onPreviewFile}
              onRemoveFile={(fileId) =>
                setDraftFileIds((current) => current.filter((id) => id !== fileId))
              }
            />
            {fileError ? (
              <div className="rounded-xl border border-negative/40 bg-negative/10 px-3 py-2 text-xs text-negative">
                {fileError}
              </div>
            ) : null}
          </div>

          <div className="space-y-3 rounded-2xl border border-term-border bg-term-surface p-3 sm:p-4">
            <div className="flex items-center justify-between gap-3">
              <div className="min-w-0 flex-1">
                <div className="text-[10px] uppercase tracking-[0.18em] text-term-text-tertiary">
                  Audit Trail
                </div>
                <div className="mt-1 truncate text-sm text-term-text">
                  {isLoadingAuditTrail
                    ? 'Loading evidence trace...'
                    : `${auditTrail?.links.length ?? 0} links, ${auditTrail?.sources.length ?? 0} sources`}
                </div>
              </div>
              <button
                type="button"
                onClick={onRefreshAuditTrail}
                className="inline-flex shrink-0 items-center gap-1.5 rounded-xl border border-term-border bg-term-bg px-2.5 py-2 text-xs uppercase tracking-[0.18em] text-term-text-tertiary transition-colors hover:border-info/60 hover:text-term-text sm:gap-2 sm:px-3"
              >
                <RefreshCw className="h-3.5 w-3.5" />
                <span className="hidden sm:inline">Refresh</span>
              </button>
            </div>

            {auditTrail ? (
              <div className="space-y-3 text-sm text-term-text-muted">
                <div>
                  <div className="text-[10px] uppercase tracking-[0.18em] text-term-text-tertiary">
                    Sources
                  </div>
                  <ul className="mt-2 space-y-2">
                    {auditTrail.sources.slice(0, 4).map((source) => (
                      <li key={source.id} className="text-xs sm:text-sm">
                        <div className="flex gap-3">
                          {typeof source.metadataJson.imageUrl === 'string' ? (
                            <img
                              src={source.metadataJson.imageUrl}
                              alt=""
                              className="h-16 w-16 flex-shrink-0 rounded object-cover"
                            />
                          ) : null}
                          <div className="min-w-0 flex-1">
                            <div className="truncate text-term-text">{source.title}</div>
                            <div className="truncate text-term-text-tertiary">
                              {[source.publisher, source.kind].filter(Boolean).join(' • ')}
                            </div>
                            {source.url ? (
                              <a
                                href={source.url}
                                target="_blank"
                                rel="noopener noreferrer"
                                className="block truncate text-info underline decoration-info/40 underline-offset-2"
                              >
                                {source.url}
                              </a>
                            ) : null}
                            {typeof source.metadataJson.excerpt === 'string' ? (
                              <p className="mt-1 line-clamp-2 text-term-text-muted">
                                {source.metadataJson.excerpt}
                              </p>
                            ) : null}
                          </div>
                        </div>
                      </li>
                    ))}
                  </ul>
                </div>
                <div>
                  <div className="text-[10px] uppercase tracking-[0.18em] text-term-text-tertiary">
                    Audit Events
                  </div>
                  <ul className="mt-2 space-y-2">
                    {auditTrail.auditEvents.slice(0, 5).map((event) => (
                      <li key={event.id} className="text-xs sm:text-sm">
                        <span className="text-term-text">{event.action}</span>
                        <span className="text-term-text-tertiary"> • {event.createdAt}</span>
                      </li>
                    ))}
                  </ul>
                </div>
              </div>
            ) : (
              <p className="text-sm text-term-text-tertiary">
                Select a note to inspect its evidence chain.
              </p>
            )}
          </div>
        </>
      ) : null}

      {isEditorFullscreen && note
        ? createPortal(
            <div
              className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4"
              onClick={() => setIsEditorFullscreen(false)}
              role="dialog"
              aria-modal="true"
              aria-label="Expanded note editor"
            >
              <div
                className="flex max-h-[90vh] w-full max-w-4xl flex-col overflow-hidden rounded-[24px] border border-term-border bg-term-elevated shadow-2xl"
                onClick={(e) => e.stopPropagation()}
              >
                <div className="flex items-center justify-between border-b border-term-border bg-term-surface px-6 py-4">
                  <div>
                    <h2 className="text-lg font-semibold text-term-text">Edit Note</h2>
                    <p className="mt-1 text-xs text-term-text-muted">{draftTitle || 'Untitled'}</p>
                  </div>
                  <button
                    type="button"
                    onClick={() => setIsEditorFullscreen(false)}
                    className="inline-flex items-center gap-1.5 rounded-xl border border-term-border bg-term-bg px-2.5 py-2 text-term-text-tertiary transition-colors hover:border-info/60 hover:text-term-text"
                    aria-label="Collapse editor"
                  >
                    <Minimize2 className="h-4 w-4" />
                  </button>
                </div>
                <div className="flex-1 overflow-y-auto p-6">
                  <ResearchEditor
                    content={draftBodyHtml}
                    embeds={draftEmbeds}
                    minRows={18}
                    className="rounded-2xl"
                    onPreviewLink={async (url) => {
                      const result = await researchBridge.previewNoteLink({ url, kind: 'article' });
                      return result.embed;
                    }}
                    onChange={(html, text, embeds) => {
                      setDraftBodyHtml(html);
                      setDraftBody(text);
                      setDraftEmbeds(embeds);
                    }}
                  />
                </div>
                <div className="flex items-center justify-between border-t border-term-border bg-term-surface px-6 py-4">
                  <p className="text-[10px] text-term-text-tertiary">
                    Press <kbd className="rounded border border-term-border bg-term-bg px-1 py-0.5">Esc</kbd> to collapse
                  </p>
                  <button
                    type="button"
                    onClick={() => setIsEditorFullscreen(false)}
                    className="rounded border border-info bg-info px-4 py-2 text-xs font-semibold text-term-bg transition-colors hover:brightness-110"
                  >
                    Done
                  </button>
                </div>
              </div>
            </div>,
            document.body,
          )
        : null}
      <ResearchFilePickerModal
        isOpen={isFilePickerOpen}
        files={workspaceFiles}
        selectedFileIds={draftFileIds}
        onClose={() => setIsFilePickerOpen(false)}
        onConfirm={(fileIds) => {
          setDraftFileIds(fileIds);
          setIsFilePickerOpen(false);
        }}
        onOpenFile={(file) => onOpenFile?.(file)}
        onPreviewFile={(file) => onPreviewFile?.(file)}
      />
    </div>
  );
};
