import React from 'react';
import {
  DndContext,
  DragOverlay,
  KeyboardSensor,
  PointerSensor,
  closestCenter,
  useSensor,
  useSensors,
} from '@dnd-kit/core';
import { SortableContext, arrayMove, sortableKeyboardCoordinates, verticalListSortingStrategy } from '@dnd-kit/sortable';
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
import { formatDirectoryName, formatPathForDisplay, cn } from '@/lib/utils';
import type { SessionGroup } from './types';
import { SortableGroupItem, SortableProjectItem } from './sortableItems';
import { formatProjectLabel } from './utils';

type ProjectSection = {
  project: {
    id: string;
    label?: string;
    normalizedPath: string;
  };
  groups: SessionGroup[];
};

type Props = {
  sectionsForRender: ProjectSection[];
  projectSections: ProjectSection[];
  activeProjectId: string | null;
  showOnlyMainWorkspace: boolean;
  hasSessionSearchQuery: boolean;
  emptyState: React.ReactNode;
  searchEmptyState: React.ReactNode;
  renderGroupSessions: (group: SessionGroup, groupKey: string, projectId?: string | null, hideGroupLabel?: boolean) => React.ReactNode;
  homeDirectory: string | null;
  collapsedProjects: Set<string>;
  hideDirectoryControls: boolean;
  projectRepoStatus: Map<string, boolean | null>;
  hoveredProjectId: string | null;
  setHoveredProjectId: (id: string | null) => void;
  isDesktopShellRuntime: boolean;
  stuckProjectHeaders: Set<string>;
  mobileVariant: boolean;
  toggleProject: (id: string) => void;
  setActiveProjectIdOnly: (id: string) => void;
  setActiveMainTab: (tab: 'chat' | 'plan' | 'git' | 'diff' | 'terminal' | 'files') => void;
  setSessionSwitcherOpen: (open: boolean) => void;
  openNewSessionDraft: (options?: { directoryOverride?: string | null }) => void;
  createWorktreeSession: () => void;
  openMultiRunLauncher: () => void;
  setEditingProjectId: (id: string | null) => void;
  setEditProjectTitle: (title: string) => void;
  editingProjectId: string | null;
  editProjectTitle: string;
  handleSaveProjectEdit: () => void;
  handleCancelProjectEdit: () => void;
  removeProject: (id: string) => void;
  projectHeaderSentinelRefs: React.MutableRefObject<Map<string, HTMLDivElement | null>>;
  settingsAutoCreateWorktree: boolean;
  getOrderedGroups: (projectId: string, groups: SessionGroup[]) => SessionGroup[];
  setGroupOrderByProject: React.Dispatch<React.SetStateAction<Map<string, string[]>>>;
};

export function SidebarProjectsList(props: Props): React.ReactNode {
  const sensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 8 } }),
    useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
  );

  if (props.projectSections.length === 0) {
    return <ScrollableOverlay outerClassName="flex-1 min-h-0" className={cn('space-y-1 pb-1 pl-2.5 pr-1', props.mobileVariant ? '' : '')}>{props.emptyState}</ScrollableOverlay>;
  }

  if (props.sectionsForRender.length === 0) {
    return <ScrollableOverlay outerClassName="flex-1 min-h-0" className={cn('space-y-1 pb-1 pl-2.5 pr-1', props.mobileVariant ? '' : '')}>{props.searchEmptyState}</ScrollableOverlay>;
  }

  return (
    <ScrollableOverlay outerClassName="flex-1 min-h-0" className={cn('space-y-1 pb-1 pl-2.5 pr-1', props.mobileVariant ? '' : '')}>
      {props.showOnlyMainWorkspace ? (
        <div className="space-y-[0.6rem] py-1">
          {(() => {
            const activeSection = props.sectionsForRender.find((section) => section.project.id === props.activeProjectId) ?? props.sectionsForRender[0];
            if (!activeSection) {
              return props.hasSessionSearchQuery ? props.searchEmptyState : props.emptyState;
            }
            const group =
              activeSection.groups.find((candidate) => candidate.isMain && candidate.sessions.length > 0)
              ?? activeSection.groups.find((candidate) => candidate.sessions.length > 0)
              ?? activeSection.groups.find((candidate) => candidate.isMain)
              ?? activeSection.groups[0];
            if (!group) {
              return <div className="py-1 text-left typography-micro text-muted-foreground">No sessions yet.</div>;
            }
            const groupKey = `${activeSection.project.id}:${group.id}`;
            return props.renderGroupSessions(group, groupKey, activeSection.project.id, props.showOnlyMainWorkspace);
          })()}
        </div>
      ) : (
        <>
          {props.sectionsForRender.map((section) => {
            const project = section.project;
            const projectKey = project.id;
            const projectLabel = formatProjectLabel(
              project.label?.trim()
              || formatDirectoryName(project.normalizedPath, props.homeDirectory)
              || project.normalizedPath,
            );
            const projectDescription = formatPathForDisplay(project.normalizedPath, props.homeDirectory);
            const isCollapsed = props.collapsedProjects.has(projectKey) && props.hideDirectoryControls;
            const isActiveProject = projectKey === props.activeProjectId;
            const isRepo = props.projectRepoStatus.get(projectKey);
            const isHovered = props.hoveredProjectId === projectKey;
            const orderedGroups = props.getOrderedGroups(projectKey, section.groups);

            return (
              <SortableProjectItem
                key={projectKey}
                id={projectKey}
                projectLabel={projectLabel}
                projectDescription={projectDescription}
                isCollapsed={isCollapsed}
                isActiveProject={isActiveProject}
                isRepo={Boolean(isRepo)}
                isHovered={isHovered}
                isDesktopShell={props.isDesktopShellRuntime}
                isStuck={props.stuckProjectHeaders.has(projectKey)}
                hideDirectoryControls={props.hideDirectoryControls}
                mobileVariant={props.mobileVariant}
                onToggle={() => props.toggleProject(projectKey)}
                onHoverChange={(hovered) => props.setHoveredProjectId(hovered ? projectKey : null)}
                onNewSession={() => {
                  if (projectKey !== props.activeProjectId) props.setActiveProjectIdOnly(projectKey);
                  props.setActiveMainTab('chat');
                  if (props.mobileVariant) props.setSessionSwitcherOpen(false);
                  props.openNewSessionDraft({ directoryOverride: project.normalizedPath });
                }}
                onNewWorktreeSession={() => {
                  if (projectKey !== props.activeProjectId) props.setActiveProjectIdOnly(projectKey);
                  props.setActiveMainTab('chat');
                  if (props.mobileVariant) props.setSessionSwitcherOpen(false);
                  props.createWorktreeSession();
                }}
                onOpenMultiRunLauncher={() => {
                  if (projectKey !== props.activeProjectId) props.setActiveProjectIdOnly(projectKey);
                  props.openMultiRunLauncher();
                }}
                onRenameStart={() => {
                  props.setEditingProjectId(projectKey);
                  props.setEditProjectTitle(project.label?.trim() || formatDirectoryName(project.normalizedPath, props.homeDirectory) || project.normalizedPath);
                }}
                onRenameSave={props.handleSaveProjectEdit}
                onRenameCancel={props.handleCancelProjectEdit}
                onRenameValueChange={props.setEditProjectTitle}
                renameValue={props.editingProjectId === projectKey ? props.editProjectTitle : ''}
                isRenaming={props.editingProjectId === projectKey}
                onClose={() => props.removeProject(projectKey)}
                sentinelRef={(el) => { props.projectHeaderSentinelRefs.current.set(projectKey, el); }}
                settingsAutoCreateWorktree={props.settingsAutoCreateWorktree}
                showCreateButtons={false}
                hideHeader
              >
                {!isCollapsed ? (
                  <div className="space-y-[0.6rem] py-1">
                    {section.groups.length > 0 ? (
                      <DndContext
                        sensors={sensors}
                        collisionDetection={closestCenter}
                        onDragEnd={(event) => {
                          const { active, over } = event;
                          if (!over || active.id === over.id) return;
                          const oldIndex = orderedGroups.findIndex((item) => item.id === active.id);
                          const newIndex = orderedGroups.findIndex((item) => item.id === over.id);
                          if (oldIndex === -1 || newIndex === -1 || oldIndex === newIndex) return;
                          const next = arrayMove(orderedGroups, oldIndex, newIndex).map((item) => item.id);
                          props.setGroupOrderByProject((prev) => {
                            const map = new Map(prev);
                            map.set(projectKey, next);
                            return map;
                          });
                        }}
                      >
                        <SortableContext items={orderedGroups.map((group) => group.id)} strategy={verticalListSortingStrategy}>
                          {orderedGroups.map((group) => {
                            const groupKey = `${projectKey}:${group.id}`;
                            return (
                              <SortableGroupItem key={group.id} id={group.id}>
                                {props.renderGroupSessions(group, groupKey, projectKey)}
                              </SortableGroupItem>
                            );
                          })}
                        </SortableContext>
                        <DragOverlay dropAnimation={null} />
                      </DndContext>
                    ) : (
                      <div className="py-1 text-left typography-micro text-muted-foreground">No sessions yet.</div>
                    )}
                  </div>
                ) : null}
              </SortableProjectItem>
            );
          })}
        </>
      )}
    </ScrollableOverlay>
  );
}
