import * as Dialog from '@radix-ui/react-dialog';
import { memo, useEffect, useMemo } from 'react';
import { useLocation, useParams } from 'react-router-dom';

import { APP_CHROME_NO_DRAG_CLASS } from '@/components/shell/app-chrome';
import { getFileName } from '@/features/file-preview';
import { WorkspaceFilePreviewPanel } from '@/features/workspace/workspace-file-preview-dialog';
import { cn } from '@/lib/cn';
import { useSidebarStore } from '@/stores/sidebar-store';
import { useWorkspaceEditorAgentStore } from '@/stores/workspace-editor-agent-store';
import { useWorkspacePanelStore } from '@/stores/workspace-panel-store';
import { useMediaQuery } from '@/lib/use-media-query';
import { useWorkspacePreviewStore } from '@/stores/workspace-preview-store';

const MD_MIN = '(min-width: 768px)';
const LG_MIN = '(min-width: 1024px)';

function usePreviewDialogInset() {
  const sidebarCollapsed = useSidebarStore((s) => s.collapsed);
  const expandedWidthPx = useSidebarStore((s) => s.expandedWidthPx);
  const workspaceOpen = useWorkspacePanelStore((s) => s.open);
  const workspaceWidthPx = useWorkspacePanelStore((s) => s.widthPx);
  const isMd = useMediaQuery(MD_MIN, true);
  const isLg = useMediaQuery(LG_MIN, true);

  return useMemo(() => {
    if (!isMd) {
      return { top: '0', left: '0', right: '0', bottom: '0' } as const;
    }
    const right = workspaceOpen ? `${workspaceWidthPx}px` : '0';
    if (!isLg) {
      // Tablet: viewport minus project-files rail only (matches “whole width − 右侧项目文件”).
      return { top: '0', left: '0', right, bottom: '0' } as const;
    }
    const left = sidebarCollapsed ? '4.5rem' : `${expandedWidthPx}px`;
    return { top: '0', left, right, bottom: '0' } as const;
  }, [isMd, isLg, sidebarCollapsed, expandedWidthPx, workspaceOpen, workspaceWidthPx]);
}

/**
 * Full workspace file preview: full viewport height. Below `md`, full bleed. From `md` to
 * below `lg`, inset only the project-files rail. At `lg+`, inset left app-sidebar and the
 * project-files rail.
 */
export const WorkspacePreviewDialog = memo(function WorkspacePreviewDialog() {
  const { pathname } = useLocation();
  const { sessionKey: sessionKeyParam } = useParams();
  const chatSessionKey =
    pathname.startsWith('/chat') && sessionKeyParam
      ? decodeURIComponent(sessionKeyParam)
      : undefined;
  const path = useWorkspacePreviewStore((s) => s.path);
  const setPath = useWorkspacePreviewStore((s) => s.setPath);
  const editorAgentId = useWorkspaceEditorAgentStore((s) => s.agentId);
  const inset = usePreviewDialogInset();
  const open = Boolean(path);

  useEffect(() => {
    if (!pathname.startsWith('/chat')) {
      setPath(null);
    }
  }, [pathname, setPath]);

  const insetStyle = { top: inset.top, left: inset.left, right: inset.right, bottom: inset.bottom };

  return (
    <Dialog.Root open={open} onOpenChange={(v) => !v && setPath(null)}>
      <Dialog.Portal>
        <Dialog.Overlay className="xopc-dialog-overlay fixed z-[65] bg-scrim" style={insetStyle} />
        <Dialog.Content
          className={cn(
            'xopc-dialog-content-pane fixed z-[66] flex min-h-0 flex-col overflow-hidden border border-edge bg-surface-panel shadow-popover outline-none',
            'dark:border-edge',
            APP_CHROME_NO_DRAG_CLASS,
          )}
          style={insetStyle}
          aria-describedby={undefined}
        >
          <Dialog.Title className="sr-only">
            {path ? getFileName(path) : 'Preview'}
          </Dialog.Title>
          <WorkspaceFilePreviewPanel
            filePath={path}
            sessionKey={chatSessionKey}
            agentId={editorAgentId.trim() || undefined}
            onClose={() => setPath(null)}
          />
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  );
});
