import { useState, useMemo } from 'react';
import {
  Folder,
  Circle,
  ChevronRight,
  ChevronDown,
  Plus,
  Pencil,
  Edit2,
  Archive,
  ArchiveRestore,
  Trash2,
  Search,
} from 'lucide-react';
import { cn } from '@/lib/utils';
import { trpc } from '@/lib/trpc';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Switch } from '@/components/ui/switch';
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from '@/components/ui/context-menu';
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from '@/components/ui/collapsible';
import { ScrollArea } from '@/components/ui/scroll-area';
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from '@/components/ui/empty';

const NO_CLIENT_KEY = '__no_client__';

type ProjectSidebarProps = {
  selectedProjectId: string | undefined;
  onSelectProject: (id: string) => void;
};

export function ProjectSidebar({ selectedProjectId, onSelectProject }: ProjectSidebarProps) {
  const utils = trpc.useUtils();

  const [showArchived, setShowArchived] = useState(false);
  const [searchQuery, setSearchQuery] = useState('');
  const [expanded, setExpanded] = useState<Set<string>>(new Set());
  const [deleteProjectId, setDeleteProjectId] = useState<{ id: string; name: string } | null>(null);
  const [renameProject, setRenameProject] = useState<{ id: string; name: string } | null>(null);
  const [renameProjectValue, setRenameProjectValue] = useState('');
  const [editDialog, setEditDialog] = useState<{ id: string; name: string; clientId: string | null } | null>(null);

  // Client action state
  const [renameClient, setRenameClient] = useState<{ id: string; name: string } | null>(null);
  const [renameClientValue, setRenameClientValue] = useState('');
  const [deleteClient, setDeleteClient] = useState<{ id: string; name: string } | null>(null);
  const [editClientValue, setEditClientValue] = useState<string>(NO_CLIENT_KEY);
  const [editSubClientValue, setEditSubClientValue] = useState<string>(NO_CLIENT_KEY);
  const [editCreatingClient, setEditCreatingClient] = useState(false);
  const [editNewClientName, setEditNewClientName] = useState('');
  const [editCreatingSubClient, setEditCreatingSubClient] = useState(false);
  const [editNewSubClientName, setEditNewSubClientName] = useState('');

  // New-project dialog state
  const [newProjectOpen, setNewProjectOpen] = useState(false);
  const [newProjectName, setNewProjectName] = useState('');
  const [newProjectClientId, setNewProjectClientId] = useState<string>(NO_CLIENT_KEY);
  const [newProjectSubClientId, setNewProjectSubClientId] = useState<string>(NO_CLIENT_KEY);
  // Inline client creation
  const [creatingClient, setCreatingClient] = useState(false);
  const [newClientName, setNewClientName] = useState('');
  // Inline sub-client creation
  const [creatingSubClient, setCreatingSubClient] = useState(false);
  const [newSubClientName, setNewSubClientName] = useState('');

  const { data: projectList = [] } = trpc.projects.list.useQuery(
    { includeArchived: showArchived },
  );
  const { data: clientList = [] } = trpc.clients.list.useQuery();

  // Derived: top-level clients and sub-clients grouped by parentId
  const topLevelClients = useMemo(
    () => clientList.filter((c) => !c.parentId),
    [clientList],
  );
  const subClientsByParent = useMemo(() => {
    const m = new Map<string, typeof clientList>();
    for (const c of clientList) {
      if (c.parentId) {
        const arr = m.get(c.parentId);
        if (arr) arr.push(c);
        else m.set(c.parentId, [c]);
      }
    }
    return m;
  }, [clientList]);

  const createClientMutation = trpc.clients.create.useMutation({
    onSuccess: () => {
      void utils.clients.list.invalidate();
    },
  });

  const createMutation = trpc.projects.create.useMutation({
    onSuccess: (data, variables) => {
      // Auto-expand the matching client group
      const groupKey = variables.clientId ?? NO_CLIENT_KEY;
      setExpanded((prev) => new Set([...prev, groupKey]));
      onSelectProject(data.id);
      void utils.projects.list.invalidate();
    },
  });

  const updateMutation = trpc.projects.update.useMutation({
    onSuccess: () => { void utils.projects.list.invalidate(); },
  });

  const deleteMutation = trpc.projects.delete.useMutation({
    onSuccess: () => {
      setDeleteProjectId(null);
      void utils.projects.list.invalidate();
    },
  });

  const updateClientMutation = trpc.clients.update.useMutation({
    onSuccess: () => {
      setRenameClient(null);
      void utils.clients.list.invalidate();
    },
  });

  const archiveByClientMutation = trpc.projects.archiveByClient.useMutation({
    onSuccess: () => { void utils.projects.list.invalidate(); },
  });

  const deleteClientMutation = trpc.clients.deleteWithCascade.useMutation({
    onSuccess: () => {
      setDeleteClient(null);
      void utils.clients.list.invalidate();
      void utils.projects.list.invalidate();
    },
  });

  // Build a client lookup map
  const clientMap = useMemo(() => {
    const m = new Map<string, string>();
    for (const c of clientList) m.set(c.id, c.name);
    return m;
  }, [clientList]);

  // Group projects by clientId, filter by search
  const grouped = useMemo(() => {
    const lowerSearch = searchQuery.toLowerCase();
    const filtered = projectList.filter((p) =>
      !searchQuery || p.name.toLowerCase().includes(lowerSearch),
    );

    const groups = new Map<string, typeof filtered>();

    // Ensure every client appears even with 0 projects
    for (const c of clientList) {
      groups.set(c.id, []);
    }

    for (const p of filtered) {
      const key = p.clientId ?? NO_CLIENT_KEY;
      const arr = groups.get(key);
      if (arr) arr.push(p);
      else groups.set(key, [p]);
    }
    return groups;
  }, [projectList, clientList, searchQuery]);

  // Count projects for a top-level client including its sub-clients
  const totalProjectCount = useMemo(() => {
    const counts = new Map<string, number>();
    for (const c of topLevelClients) {
      let count = (grouped.get(c.id) ?? []).length;
      for (const sc of subClientsByParent.get(c.id) ?? []) {
        count += (grouped.get(sc.id) ?? []).length;
      }
      counts.set(c.id, count);
    }
    return counts;
  }, [topLevelClients, subClientsByParent, grouped]);

  // Auto-expand all groups when searching
  const effectiveExpanded = useMemo(() => {
    if (searchQuery) {
      return new Set([...grouped.keys()]);
    }
    return expanded;
  }, [searchQuery, grouped, expanded]);

  function toggleExpanded(key: string) {
    setExpanded((prev) => {
      const next = new Set(prev);
      next.has(key) ? next.delete(key) : next.add(key);
      return next;
    });
  }

  function handleOpenNewProject() {
    setNewProjectName('');
    setNewProjectClientId(NO_CLIENT_KEY);
    setNewProjectSubClientId(NO_CLIENT_KEY);
    setCreatingClient(false);
    setNewClientName('');
    setCreatingSubClient(false);
    setNewSubClientName('');
    setNewProjectOpen(true);
  }

  async function handleCreateProject() {
    const name = newProjectName.trim();
    if (!name) return;

    let resolvedClientId: string | undefined;

    // If creating a brand-new client first
    if (creatingClient && newClientName.trim()) {
      const result = await createClientMutation.mutateAsync({ name: newClientName.trim() });
      resolvedClientId = result.id;

      // If also creating a sub-client under the new client
      if (creatingSubClient && newSubClientName.trim()) {
        const subResult = await createClientMutation.mutateAsync({
          name: newSubClientName.trim(),
          parentId: resolvedClientId,
        });
        resolvedClientId = subResult.id;
      }
    } else if (newProjectClientId !== NO_CLIENT_KEY) {
      // User picked an existing client
      if (creatingSubClient && newSubClientName.trim()) {
        // Create a new sub-client under the selected client
        const subResult = await createClientMutation.mutateAsync({
          name: newSubClientName.trim(),
          parentId: newProjectClientId,
        });
        resolvedClientId = subResult.id;
      } else if (newProjectSubClientId !== NO_CLIENT_KEY) {
        // User picked an existing sub-client
        resolvedClientId = newProjectSubClientId;
      } else {
        // Just the parent client, no sub-client
        resolvedClientId = newProjectClientId;
      }
    }

    createMutation.mutate(
      { name, clientId: resolvedClientId },
      { onSuccess: () => setNewProjectOpen(false) },
    );
  }

  function handleArchiveToggle(id: string, currentStatus: string | null) {
    const newStatus = currentStatus === 'archived' ? 'active' : 'archived';
    updateMutation.mutate({ id, status: newStatus as 'active' | 'archived' });
  }

  function handleEditOpen(project: { id: string; name: string; clientId: string | null }) {
    setEditDialog(project);
    setEditCreatingClient(false);
    setEditNewClientName('');
    setEditCreatingSubClient(false);
    setEditNewSubClientName('');
    if (!project.clientId) {
      setEditClientValue(NO_CLIENT_KEY);
      setEditSubClientValue(NO_CLIENT_KEY);
    } else {
      // Check if clientId is a sub-client
      const client = clientList.find((c) => c.id === project.clientId);
      if (client?.parentId) {
        // It's a sub-client — set parent as client, this as sub-client
        setEditClientValue(client.parentId);
        setEditSubClientValue(client.id);
      } else {
        setEditClientValue(project.clientId);
        setEditSubClientValue(NO_CLIENT_KEY);
      }
    }
  }

  async function handleEditSave() {
    if (!editDialog) return;

    let resolvedClientId: string | null;

    if (editCreatingClient && editNewClientName.trim()) {
      // Create a new client
      const result = await createClientMutation.mutateAsync({ name: editNewClientName.trim() });
      let parentId = result.id;

      if (editCreatingSubClient && editNewSubClientName.trim()) {
        // Also create a sub-client under the new client
        const subResult = await createClientMutation.mutateAsync({
          name: editNewSubClientName.trim(),
          parentId,
        });
        resolvedClientId = subResult.id;
      } else {
        resolvedClientId = parentId;
      }
    } else if (editCreatingSubClient && editNewSubClientName.trim() && editClientValue !== NO_CLIENT_KEY) {
      // Create a new sub-client under the selected parent
      const result = await createClientMutation.mutateAsync({
        name: editNewSubClientName.trim(),
        parentId: editClientValue,
      });
      resolvedClientId = result.id;
    } else if (editSubClientValue !== NO_CLIENT_KEY) {
      resolvedClientId = editSubClientValue;
    } else if (editClientValue !== NO_CLIENT_KEY) {
      resolvedClientId = editClientValue;
    } else {
      resolvedClientId = null;
    }

    updateMutation.mutate(
      { id: editDialog.id, clientId: resolvedClientId },
      { onSuccess: () => setEditDialog(null) },
    );
  }


  // Sort groups: only top-level clients + NO_CLIENT_KEY, sub-clients rendered nested
  const sortedGroupKeys = useMemo(() => {
    // Only include top-level clients and the NO_CLIENT_KEY group
    const topLevelIds = new Set(topLevelClients.map((c) => c.id));
    const keys = [...grouped.keys()].filter(
      (k) => k === NO_CLIENT_KEY || topLevelIds.has(k),
    );
    return keys.sort((a, b) => {
      if (a === NO_CLIENT_KEY) return 1;
      if (b === NO_CLIENT_KEY) return -1;
      const nameA = clientMap.get(a) ?? '';
      const nameB = clientMap.get(b) ?? '';
      return nameA.localeCompare(nameB);
    });
  }, [grouped, clientMap, topLevelClients]);

  const totalProjects = projectList.length;

  return (
    <div className="flex flex-col h-full border-r border-border w-60 shrink-0">
      {/* Header */}
      <div className="flex items-center justify-between px-3 py-2.5 shrink-0">
        <h4 className="text-lg font-semibold text-foreground">Projects</h4>
        <Button
          variant="outline"
          size="icon"
          onClick={handleOpenNewProject}
          disabled={createMutation.isPending}
          aria-label="New Project"
        >
          <Plus />
        </Button>
      </div>

      {/* Search */}
      <div className="px-3 pb-2 shrink-0">
        <div className="relative">
          <Search className="absolute left-2 top-1/2 -translate-y-1/2 size-3.5 text-muted-foreground" />
          <Input
            placeholder="Search projects..."
            className="h-7 text-sm pl-7"
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
          />
        </div>
      </div>

      {/* Show archived toggle */}
      <div className="flex items-center justify-between px-3 pb-2 shrink-0">
        <label htmlFor="show-archived" className="text-xs text-muted-foreground cursor-pointer">
          Show archived
        </label>
        <Switch
          id="show-archived"
          checked={showArchived}
          onCheckedChange={setShowArchived}
          className="scale-75"
        />
      </div>

      {/* Project tree */}
      <ScrollArea className="flex-1 py-1 px-1">
        {totalProjects === 0 ? (
          <Empty>
            <EmptyHeader>
              <EmptyMedia variant="icon">
                <Folder />
              </EmptyMedia>
              <EmptyTitle>No projects yet</EmptyTitle>
              <EmptyDescription>
                Get started by adding your first project.
              </EmptyDescription>
            </EmptyHeader>
            <EmptyContent>
              <Button
                variant="outline"
                size="sm"
                onClick={handleOpenNewProject}
                disabled={createMutation.isPending}
              >
                <Plus className="mr-1 h-4 w-4" />
                Add Project
              </Button>
            </EmptyContent>
          </Empty>
        ) : sortedGroupKeys.length === 0 && clientList.length === 0 ? (
          <div className="text-xs text-muted-foreground px-3 py-4 text-center">
            No projects match your search.
          </div>
        ) : (
          <>
          {/* Client groups */}
          {sortedGroupKeys.filter((k) => k !== NO_CLIENT_KEY).map((groupKey) => {
            const groupProjects = grouped.get(groupKey) ?? [];
            const groupName = clientMap.get(groupKey) ?? 'Unknown Client';
            const isOpen = effectiveExpanded.has(groupKey);

            return (
              <Collapsible
                key={groupKey}
                open={isOpen}
                onOpenChange={() => toggleExpanded(groupKey)}
              >
                <ContextMenu>
                  <ContextMenuTrigger asChild>
                    <CollapsibleTrigger asChild>
                      <div className="flex items-center h-7 rounded-md text-sm cursor-pointer hover:bg-accent transition-colors px-2">
                        {isOpen ? (
                          <ChevronDown className="size-3 shrink-0 text-muted-foreground mr-1" />
                        ) : (
                          <ChevronRight className="size-3 shrink-0 text-muted-foreground mr-1" />
                        )}
                        <Folder className="size-3.5 shrink-0 text-muted-foreground mr-1.5" />
                        <span className="flex-1 min-w-0 truncate font-medium text-foreground">
                          {groupName}
                        </span>
                        <span className="text-xs text-muted-foreground ml-1">
                          {totalProjectCount.get(groupKey) ?? groupProjects.length}
                        </span>
                      </div>
                    </CollapsibleTrigger>
                  </ContextMenuTrigger>
                  <ContextMenuContent className="min-w-[160px]">
                    <ContextMenuItem
                      onClick={() => {
                        setRenameClient({ id: groupKey, name: groupName });
                        setRenameClientValue(groupName);
                      }}
                    >
                      <Pencil />
                      Rename
                    </ContextMenuItem>
                    <ContextMenuItem
                      onClick={() => {
                        const allArchived = groupProjects.every((p) => p.status === 'archived');
                        archiveByClientMutation.mutate({
                          clientId: groupKey,
                          status: allArchived ? 'active' : 'archived',
                        });
                      }}
                    >
                      {groupProjects.every((p) => p.status === 'archived') ? (
                        <>
                          <ArchiveRestore />
                          Unarchive All
                        </>
                      ) : (
                        <>
                          <Archive />
                          Archive All
                        </>
                      )}
                    </ContextMenuItem>
                    <ContextMenuSeparator />
                    <ContextMenuItem
                      variant="destructive"
                      onClick={() => {
                        setDeleteClient({ id: groupKey, name: groupName });
                      }}
                    >
                      <Trash2 />
                      Delete
                    </ContextMenuItem>
                  </ContextMenuContent>
                </ContextMenu>

                <CollapsibleContent>
                  {/* Sub-clients nested under this parent */}
                  {(subClientsByParent.get(groupKey) ?? []).map((subClient) => {
                    const subProjects = grouped.get(subClient.id) ?? [];
                    const subIsOpen = effectiveExpanded.has(subClient.id);
                    const subName = subClient.name;

                    return (
                      <Collapsible
                        key={subClient.id}
                        open={subIsOpen}
                        onOpenChange={() => toggleExpanded(subClient.id)}
                      >
                        <ContextMenu>
                          <ContextMenuTrigger asChild>
                            <CollapsibleTrigger asChild>
                              <div
                                className="flex items-center h-7 rounded-md text-sm cursor-pointer hover:bg-accent transition-colors"
                                style={{ paddingLeft: '20px', paddingRight: '8px' }}
                              >
                                {subIsOpen ? (
                                  <ChevronDown className="size-3 shrink-0 text-muted-foreground mr-1" />
                                ) : (
                                  <ChevronRight className="size-3 shrink-0 text-muted-foreground mr-1" />
                                )}
                                <Folder className="size-3 shrink-0 text-muted-foreground mr-1.5" />
                                <span className="flex-1 min-w-0 truncate font-medium text-foreground">
                                  {subName}
                                </span>
                                <span className="text-xs text-muted-foreground ml-1">
                                  {subProjects.length}
                                </span>
                              </div>
                            </CollapsibleTrigger>
                          </ContextMenuTrigger>
                          <ContextMenuContent className="min-w-[160px]">
                            <ContextMenuItem
                              onClick={() => {
                                setRenameClient({ id: subClient.id, name: subName });
                                setRenameClientValue(subName);
                              }}
                            >
                              <Pencil />
                              Rename
                            </ContextMenuItem>
                            <ContextMenuItem
                              onClick={() => {
                                const allArchived = subProjects.every((p) => p.status === 'archived');
                                archiveByClientMutation.mutate({
                                  clientId: subClient.id,
                                  status: allArchived ? 'active' : 'archived',
                                });
                              }}
                            >
                              {subProjects.every((p) => p.status === 'archived') ? (
                                <>
                                  <ArchiveRestore />
                                  Unarchive All
                                </>
                              ) : (
                                <>
                                  <Archive />
                                  Archive All
                                </>
                              )}
                            </ContextMenuItem>
                            <ContextMenuSeparator />
                            <ContextMenuItem
                              variant="destructive"
                              onClick={() => {
                                setDeleteClient({ id: subClient.id, name: subName });
                              }}
                            >
                              <Trash2 />
                              Delete
                            </ContextMenuItem>
                          </ContextMenuContent>
                        </ContextMenu>

                        <CollapsibleContent>
                          {subProjects.map((project) => (
                            <ContextMenu key={project.id}>
                              <ContextMenuTrigger asChild>
                                <div
                                  className={cn(
                                    'group flex items-center h-7 rounded-md text-sm cursor-pointer hover:bg-accent transition-colors',
                                    selectedProjectId === project.id && 'bg-sidebar-accent',
                                    project.status === 'archived' && 'opacity-60',
                                  )}
                                  style={{ paddingLeft: '40px', paddingRight: '4px' }}
                                  onClick={() => onSelectProject(project.id)}
                                >
                                  <Circle className="size-2.5 shrink-0 text-muted-foreground mr-1.5" />
                                  <span className="flex-1 min-w-0 truncate text-foreground">
                                    {project.name}
                                  </span>
                                </div>
                              </ContextMenuTrigger>
                              <ContextMenuContent className="min-w-[152px]">
                                <ContextMenuItem
                                  onClick={() => {
                                    setRenameProject({ id: project.id, name: project.name });
                                    setRenameProjectValue(project.name);
                                  }}
                                >
                                  <Pencil />
                                  Rename
                                </ContextMenuItem>
                                <ContextMenuItem
                                  onClick={() => {
                                    handleEditOpen({
                                      id: project.id,
                                      name: project.name,
                                      clientId: project.clientId,
                                    });
                                  }}
                                >
                                  <Edit2 />
                                  Edit Client
                                </ContextMenuItem>
                                <ContextMenuItem
                                  onClick={() => {
                                    handleArchiveToggle(project.id, project.status);
                                  }}
                                >
                                  {project.status === 'archived' ? (
                                    <>
                                      <ArchiveRestore />
                                      Unarchive
                                    </>
                                  ) : (
                                    <>
                                      <Archive />
                                      Archive
                                    </>
                                  )}
                                </ContextMenuItem>
                                <ContextMenuSeparator />
                                <ContextMenuItem
                                  variant="destructive"
                                  onClick={() => {
                                    setDeleteProjectId({ id: project.id, name: project.name });
                                  }}
                                >
                                  <Trash2 />
                                  Delete
                                </ContextMenuItem>
                              </ContextMenuContent>
                            </ContextMenu>
                          ))}
                        </CollapsibleContent>
                      </Collapsible>
                    );
                  })}

                  {/* Direct projects under this client */}
                  {groupProjects.map((project) => (
                    <ContextMenu key={project.id}>
                      <ContextMenuTrigger asChild>
                        <div
                          className={cn(
                            'group flex items-center h-7 rounded-md text-sm cursor-pointer hover:bg-accent transition-colors',
                            selectedProjectId === project.id && 'bg-sidebar-accent',
                            project.status === 'archived' && 'opacity-60',
                          )}
                          style={{ paddingLeft: '28px', paddingRight: '4px' }}
                          onClick={() => onSelectProject(project.id)}
                        >
                          <Circle className="size-2.5 shrink-0 text-muted-foreground mr-1.5" />
                          <span className="flex-1 min-w-0 truncate text-foreground">
                            {project.name}
                          </span>
                        </div>
                      </ContextMenuTrigger>
                      <ContextMenuContent className="min-w-[152px]">
                        <ContextMenuItem
                          onClick={() => {
                            setRenameProject({ id: project.id, name: project.name });
                            setRenameProjectValue(project.name);
                          }}
                        >
                          <Pencil />
                          Rename
                        </ContextMenuItem>
                        <ContextMenuItem
                          onClick={() => {
                            handleEditOpen({
                              id: project.id,
                              name: project.name,
                              clientId: project.clientId,
                            });
                          }}
                        >
                          <Edit2 />
                          Edit Client
                        </ContextMenuItem>
                        <ContextMenuItem
                          onClick={() => {
                            handleArchiveToggle(project.id, project.status);
                          }}
                        >
                          {project.status === 'archived' ? (
                            <>
                              <ArchiveRestore />
                              Unarchive
                            </>
                          ) : (
                            <>
                              <Archive />
                              Archive
                            </>
                          )}
                        </ContextMenuItem>
                        <ContextMenuSeparator />
                        <ContextMenuItem
                          variant="destructive"
                          onClick={() => {
                            setDeleteProjectId({ id: project.id, name: project.name });
                          }}
                        >
                          <Trash2 />
                          Delete
                        </ContextMenuItem>
                      </ContextMenuContent>
                    </ContextMenu>
                  ))}
                </CollapsibleContent>
              </Collapsible>
            );
          })}

          {/* Unassigned projects (no client) — rendered flat at root level */}
          {(grouped.get(NO_CLIENT_KEY) ?? []).map((project) => (
            <ContextMenu key={project.id}>
              <ContextMenuTrigger asChild>
                <div
                  className={cn(
                    'group flex items-center h-7 rounded-md text-sm cursor-pointer hover:bg-accent transition-colors px-2',
                    selectedProjectId === project.id && 'bg-sidebar-accent',
                    project.status === 'archived' && 'opacity-60',
                  )}
                  onClick={() => onSelectProject(project.id)}
                >
                  <Circle className="size-2.5 shrink-0 text-muted-foreground mr-1.5" />
                  <span className="flex-1 min-w-0 truncate text-foreground">
                    {project.name}
                  </span>
                </div>
              </ContextMenuTrigger>
              <ContextMenuContent className="min-w-[152px]">
                <ContextMenuItem
                  onClick={() => {
                    setRenameProject({ id: project.id, name: project.name });
                    setRenameProjectValue(project.name);
                  }}
                >
                  <Pencil />
                  Rename
                </ContextMenuItem>
                <ContextMenuItem
                  onClick={() => {
                    handleEditOpen({
                      id: project.id,
                      name: project.name,
                      clientId: project.clientId,
                    });
                  }}
                >
                  <Edit2 />
                  Edit Client
                </ContextMenuItem>
                <ContextMenuItem
                  onClick={() => {
                    handleArchiveToggle(project.id, project.status);
                  }}
                >
                  {project.status === 'archived' ? (
                    <>
                      <ArchiveRestore />
                      Unarchive
                    </>
                  ) : (
                    <>
                      <Archive />
                      Archive
                    </>
                  )}
                </ContextMenuItem>
                <ContextMenuSeparator />
                <ContextMenuItem
                  variant="destructive"
                  onClick={() => {
                    setDeleteProjectId({ id: project.id, name: project.name });
                  }}
                >
                  <Trash2 />
                  Delete
                </ContextMenuItem>
              </ContextMenuContent>
            </ContextMenu>
          ))}
          </>
        )}
      </ScrollArea>

      {/* Rename project dialog */}
      <Dialog
        open={!!renameProject}
        onOpenChange={(open) => {
          if (!open) setRenameProject(null);
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Rename Project</DialogTitle>
            <DialogDescription>
              Enter a new name for &ldquo;{renameProject?.name}&rdquo;.
            </DialogDescription>
          </DialogHeader>
          <Input
            value={renameProjectValue}
            onChange={(e) => setRenameProjectValue(e.target.value)}
            placeholder="Project name"
            autoFocus
          />
          <DialogFooter>
            <Button variant="outline" onClick={() => setRenameProject(null)}>
              Cancel
            </Button>
            <Button
              onClick={() => {
                if (renameProject && renameProjectValue.trim()) {
                  updateMutation.mutate(
                    { id: renameProject.id, name: renameProjectValue.trim() },
                    { onSuccess: () => setRenameProject(null) },
                  );
                }
              }}
              disabled={!renameProjectValue.trim() || updateMutation.isPending}
            >
              {updateMutation.isPending ? 'Saving\u2026' : 'Save'}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Delete confirmation */}
      <AlertDialog
        open={!!deleteProjectId}
        onOpenChange={(open) => {
          if (!open && !deleteMutation.isPending) setDeleteProjectId(null);
        }}
      >
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>
              Delete &ldquo;{deleteProjectId?.name}&rdquo;?
            </AlertDialogTitle>
            <AlertDialogDescription>
              This will delete the project. Tasks assigned to this project will become unassigned. This action cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={deleteMutation.isPending}>Cancel</AlertDialogCancel>
            <AlertDialogAction
              className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
              onClick={() => {
                if (deleteProjectId) deleteMutation.mutate({ id: deleteProjectId.id });
              }}
              disabled={deleteMutation.isPending}
            >
              {deleteMutation.isPending ? 'Deleting\u2026' : 'Delete'}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {/* New Project dialog */}
      <Dialog open={newProjectOpen} onOpenChange={setNewProjectOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>New Project</DialogTitle>
            <DialogDescription>
              Give your project a name and optionally assign it to a client.
            </DialogDescription>
          </DialogHeader>

          <div className="flex flex-col gap-4 py-2">
            {/* Project name */}
            <div className="flex flex-col gap-1.5">
              <label htmlFor="new-project-name" className="text-sm font-medium">Project Name</label>
              <Input
                id="new-project-name"
                placeholder="e.g. Website Redesign"
                value={newProjectName}
                onChange={(e) => setNewProjectName(e.target.value)}
                autoFocus
              />
            </div>

            {/* Client selection */}
            <div className="flex flex-col gap-1.5">
              <label className="text-sm font-medium">Client <span className="text-muted-foreground font-normal">(optional)</span></label>
              {creatingClient ? (
                <div className="flex items-center gap-2">
                  <Input
                    placeholder="New client name"
                    value={newClientName}
                    onChange={(e) => setNewClientName(e.target.value)}
                    className="flex-1"
                  />
                  <Button
                    variant="ghost"
                    size="sm"
                    onClick={() => {
                      setCreatingClient(false);
                      setNewClientName('');
                      setCreatingSubClient(false);
                      setNewSubClientName('');
                    }}
                  >
                    Cancel
                  </Button>
                </div>
              ) : (
                <div className="flex items-center gap-2">
                  <Select
                    value={newProjectClientId}
                    onValueChange={(v) => {
                      setNewProjectClientId(v);
                      setNewProjectSubClientId(NO_CLIENT_KEY);
                      setCreatingSubClient(false);
                      setNewSubClientName('');
                    }}
                  >
                    <SelectTrigger className="flex-1">
                      <SelectValue placeholder="Select a client" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value={NO_CLIENT_KEY}>None (Internal)</SelectItem>
                      {topLevelClients.map((c) => (
                        <SelectItem key={c.id} value={c.id}>{c.name}</SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={() => setCreatingClient(true)}
                  >
                    <Plus className="size-3.5 mr-1" />New
                  </Button>
                </div>
              )}
            </div>

            {/* Sub-client selection — only when a client is selected or being created */}
            {(newProjectClientId !== NO_CLIENT_KEY || (creatingClient && newClientName.trim())) && (
              <div className="flex flex-col gap-1.5">
                <label className="text-sm font-medium">Sub-client <span className="text-muted-foreground font-normal">(optional)</span></label>
                {creatingSubClient ? (
                  <div className="flex items-center gap-2">
                    <Input
                      placeholder="New sub-client name"
                      value={newSubClientName}
                      onChange={(e) => setNewSubClientName(e.target.value)}
                      className="flex-1"
                    />
                    <Button
                      variant="ghost"
                      size="sm"
                      onClick={() => {
                        setCreatingSubClient(false);
                        setNewSubClientName('');
                      }}
                    >
                      Cancel
                    </Button>
                  </div>
                ) : creatingClient ? (
                  /* When creating a new client there are no existing sub-clients to pick */
                  <Button
                    variant="outline"
                    size="sm"
                    className="w-fit"
                    onClick={() => setCreatingSubClient(true)}
                  >
                    <Plus className="size-3.5 mr-1" />New Sub-client
                  </Button>
                ) : (
                  <div className="flex items-center gap-2">
                    <Select
                      value={newProjectSubClientId}
                      onValueChange={setNewProjectSubClientId}
                    >
                      <SelectTrigger className="flex-1">
                        <SelectValue placeholder="Select a sub-client" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value={NO_CLIENT_KEY}>None</SelectItem>
                        {(subClientsByParent.get(newProjectClientId) ?? []).map((sc) => (
                          <SelectItem key={sc.id} value={sc.id}>{sc.name}</SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                    <Button
                      variant="outline"
                      size="sm"
                      onClick={() => setCreatingSubClient(true)}
                    >
                      <Plus className="size-3.5 mr-1" />New
                    </Button>
                  </div>
                )}
              </div>
            )}
          </div>

          <DialogFooter>
            <Button variant="outline" onClick={() => setNewProjectOpen(false)}>Cancel</Button>
            <Button
              onClick={handleCreateProject}
              disabled={!newProjectName.trim() || createMutation.isPending || createClientMutation.isPending}
            >
              {createMutation.isPending || createClientMutation.isPending ? 'Creating…' : 'Create Project'}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Delete client confirmation */}
      <AlertDialog
        open={!!deleteClient}
        onOpenChange={(open) => {
          if (!open && !deleteClientMutation.isPending) setDeleteClient(null);
        }}
      >
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>
              Delete &ldquo;{deleteClient?.name}&rdquo;?
            </AlertDialogTitle>
            <AlertDialogDescription>
              This will delete the client and all its projects. Tasks assigned to those projects will become unassigned. This action cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={deleteClientMutation.isPending}>Cancel</AlertDialogCancel>
            <AlertDialogAction
              className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
              onClick={() => {
                if (deleteClient) deleteClientMutation.mutate({ id: deleteClient.id });
              }}
              disabled={deleteClientMutation.isPending}
            >
              {deleteClientMutation.isPending ? 'Deleting\u2026' : 'Delete'}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {/* Rename client dialog */}
      <Dialog
        open={!!renameClient}
        onOpenChange={(open) => {
          if (!open) setRenameClient(null);
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Rename Client</DialogTitle>
            <DialogDescription>
              Enter a new name for &ldquo;{renameClient?.name}&rdquo;.
            </DialogDescription>
          </DialogHeader>
          <Input
            value={renameClientValue}
            onChange={(e) => setRenameClientValue(e.target.value)}
            placeholder="Client name"
            autoFocus
          />
          <DialogFooter>
            <Button variant="outline" onClick={() => setRenameClient(null)}>
              Cancel
            </Button>
            <Button
              onClick={() => {
                if (renameClient && renameClientValue.trim()) {
                  updateClientMutation.mutate({ id: renameClient.id, name: renameClientValue.trim() });
                }
              }}
              disabled={!renameClientValue.trim() || updateClientMutation.isPending}
            >
              {updateClientMutation.isPending ? 'Saving\u2026' : 'Save'}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Edit client dialog */}
      <Dialog
        open={!!editDialog}
        onOpenChange={(open) => {
          if (!open) setEditDialog(null);
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Edit Project Client</DialogTitle>
            <DialogDescription>
              Assign &ldquo;{editDialog?.name}&rdquo; to a client or leave as internal.
            </DialogDescription>
          </DialogHeader>
          <div className="flex flex-col gap-4 py-2">
            <div className="flex flex-col gap-1.5">
              <label className="text-sm font-medium">Client</label>
              {editCreatingClient ? (
                <div className="flex items-center gap-2">
                  <Input
                    placeholder="New client name"
                    value={editNewClientName}
                    onChange={(e) => setEditNewClientName(e.target.value)}
                    className="flex-1"
                  />
                  <Button
                    variant="ghost"
                    size="sm"
                    onClick={() => {
                      setEditCreatingClient(false);
                      setEditNewClientName('');
                      setEditCreatingSubClient(false);
                      setEditNewSubClientName('');
                    }}
                  >
                    Cancel
                  </Button>
                </div>
              ) : (
                <div className="flex items-center gap-2">
                  <Select
                    value={editClientValue}
                    onValueChange={(v) => {
                      setEditClientValue(v);
                      setEditSubClientValue(NO_CLIENT_KEY);
                      setEditCreatingSubClient(false);
                      setEditNewSubClientName('');
                    }}
                  >
                    <SelectTrigger className="flex-1">
                      <SelectValue placeholder="Select a client" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value={NO_CLIENT_KEY}>No Client (Internal)</SelectItem>
                      {topLevelClients.map((c) => (
                        <SelectItem key={c.id} value={c.id}>
                          {c.name}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={() => setEditCreatingClient(true)}
                  >
                    <Plus className="size-3.5 mr-1" />New
                  </Button>
                </div>
              )}
            </div>

            {(editClientValue !== NO_CLIENT_KEY || (editCreatingClient && editNewClientName.trim())) && (
              <div className="flex flex-col gap-1.5">
                <label className="text-sm font-medium">Sub-client <span className="text-muted-foreground font-normal">(optional)</span></label>
                {editCreatingSubClient ? (
                  <div className="flex items-center gap-2">
                    <Input
                      placeholder="New sub-client name"
                      value={editNewSubClientName}
                      onChange={(e) => setEditNewSubClientName(e.target.value)}
                      className="flex-1"
                    />
                    <Button
                      variant="ghost"
                      size="sm"
                      onClick={() => {
                        setEditCreatingSubClient(false);
                        setEditNewSubClientName('');
                      }}
                    >
                      Cancel
                    </Button>
                  </div>
                ) : editCreatingClient ? (
                  <Button
                    variant="outline"
                    size="sm"
                    className="w-fit"
                    onClick={() => setEditCreatingSubClient(true)}
                  >
                    <Plus className="size-3.5 mr-1" />New Sub-client
                  </Button>
                ) : (
                  <div className="flex items-center gap-2">
                    <Select
                      value={editSubClientValue}
                      onValueChange={setEditSubClientValue}
                    >
                      <SelectTrigger className="flex-1">
                        <SelectValue placeholder="Select a sub-client" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value={NO_CLIENT_KEY}>None</SelectItem>
                        {(subClientsByParent.get(editClientValue) ?? []).map((sc) => (
                          <SelectItem key={sc.id} value={sc.id}>
                            {sc.name}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                    <Button
                      variant="outline"
                      size="sm"
                      onClick={() => setEditCreatingSubClient(true)}
                    >
                      <Plus className="size-3.5 mr-1" />New
                    </Button>
                  </div>
                )}
              </div>
            )}
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setEditDialog(null)}>
              Cancel
            </Button>
            <Button onClick={handleEditSave} disabled={updateMutation.isPending || createClientMutation.isPending}>
              {updateMutation.isPending || createClientMutation.isPending ? 'Saving\u2026' : 'Save'}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
