"use client"

import { memo, type Dispatch, type MouseEvent, type RefObject, type SetStateAction } from "react"
import { Icon } from "@iconify/react"
import {
  Archive,
  CalendarClock,
  Clock,
  FolderInput,
  Forward,
  Inbox as InboxIcon,
  ListTodo,
  Mail,
  MailOpen,
  Paperclip,
  Pencil,
  Reply,
  ReplyAll,
  Search,
  Send,
  ShieldAlert,
  SquareArrowOutUpRight,
  Star,
  Tag,
  Trash2,
  VolumeX,
} from "lucide-react"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { ContactHoverCard } from "@/components/gmail/contact-hover-card"
import { EmailLabelPickerBlock } from "@/components/gmail/email-label-picker-block"
import type { CatalogLabelPresence } from "@/components/gmail/email-label-picker-block"
import { MailInboxCategoryTabIcons } from "@/components/gmail/mail-inbox-category-tab-icons"
import {
  MailLabelPillStrip,
} from "@/components/gmail/mail-label-pills"
import { MailListSwipeRow } from "@/components/gmail/mail-list-swipe-row"
import { MailDateText } from "@/components/gmail/mail-date-text"
import { EmailListAttachmentRow } from "@/components/gmail/email-list/attachments/email-list-attachment-row"
import {
  MoveToContextMenuItems,
} from "@/components/gmail/email-list/move-to-menu-items"
import type { MoveTarget, MailMoveTargets } from "@/components/gmail/move-to-menu-items"
import { cn } from "@/lib/utils"
import type { Email } from "@/lib/email-data"
import {
  getThreadMessageCount,
  isListRowRead,
} from "@/lib/mail-thread"
import { threadStoreId } from "@/lib/mail-settings/list-row-id"
import { resolveSenderEmail } from "@/lib/sender-display"
import { VIDEO_CONFERENCE_LOGOS } from "@/lib/calendar-invitation"
import {
  MAIL_MENU_SURFACE_CLASS,
  MAIL_MENU_SURFACE_WIDE_CLASS,
} from "@/lib/mail-chrome-classes"
import { readXsMatches } from "@/hooks/use-xs"
import type { LabelRowItem, FolderTreeNode } from "@/lib/sidebar-nav-data"
import {
  contextMenuTargetIdsForRow,
  formatScheduledDateTimeDisplay,
  importantSignalIcon,
  listRowCheckboxClass,
  listRowQuickHoverTrayToneClass,
  parseDatetimeLocalToIso,
  scheduledIsoToDatetimeLocalValue,
} from "@/components/gmail/email-list/email-list-helpers"
import type { ListMailIndex } from "@/components/gmail/email-list/list-mail-index"

type ListRowExtras = {
  invitationById: Map<string, ReturnType<typeof import("@/lib/resolve-email-calendar-invitation").resolveParsedCalendarInvitation>>
  attachmentsById: Map<string, import("@/lib/email-data").EmailAttachment[]>
  categoryTabsById: Map<string, import("@/lib/inbox-category-tabs").InboxCategoryTabIcon[]>
}

export type EmailListRowProps = {
  email: Email
  allEmails: Email[]
  emailById: Map<string, Email>
  listMailIndex: ListMailIndex
  listRowExtras: ListRowExtras
  starredEmails: string[]
  importantEmails: string[]
  readOverrides: Record<string, boolean>
  conversationMode: boolean
  savedThreadReplyDrafts: Record<string, unknown>
  selectedEmails: string[]
  selectedFolder: string
  splitView: boolean
  openMailId: string | null
  isXs: boolean
  isMd: boolean
  density: string
  mobileSelectionMode: boolean
  touchListSwipeEnabled: boolean
  openSwipeRowId: string | null
  setOpenSwipeRowId: (id: string | null) => void
  listRowLabelBgByTextLower: Map<string, string>
  sidebarNav: {
    emailLabelToSidebarFolderId: Record<string, string>
    getNavItemPrefs: (id: string) => { messages: string }
    labelRows: LabelRowItem[]
    folderTree: FolderTreeNode[]
  }
  rescheduleTarget: {
    id: string
    value: string
    panelOpen: boolean
  } | null
  setRescheduleTarget: Dispatch<SetStateAction<{
    id: string
    value: string
    panelOpen: boolean
  } | null>>
  rescheduleDismissTimeoutsRef: RefObject<Map<string, ReturnType<typeof setTimeout>>>
  scheduleReschedulePopoverDismiss: (rowId: string) => void
  rowContextMenuOpenedAtRef: RefObject<number>
  contextMenuTargetIdsRef: RefObject<string[]>
  lastSelectionAnchorIdRef: RefObject<string | null>
  setSelectedEmails: Dispatch<SetStateAction<string[]>>
  setLabelPickerQuery: (q: string) => void
  labelPickerQuery: string
  catalogLabels: string[]
  resolveLabelVisual: (label: string) => ReturnType<typeof import("@/lib/label-picker-visual").resolveLabelPickerVisual>
  getCatalogLabelPresence: (ids: string[], catalogLabel: string) => CatalogLabelPresence
  toggleLabelOnEmails: (ids: string[], label: string) => void
  addLabelToEmails: (ids: string[], label: string) => void
  moveTargets: MailMoveTargets
  moveEmailsToTarget: (emailIds: string[], targetId: string) => void
  cmScheduledRescheduleValue: string
  setCmScheduledRescheduleValue: (v: string) => void
  mailActions: {
    hideEmail: (id: string) => void
    markNotSpam: (id: string) => void
    unhideEmail: (id: string) => void
  }
  setReadOverrides: (updater: (prev: Record<string, boolean>) => Record<string, boolean>) => void
  onSelectFolder?: (folder: string) => void
  toggleSelect: (id: string) => void
  handleRowCheckboxClickCapture: (id: string, e: MouseEvent) => void
  handleRowActivate: (email: Email) => void
  startRowDrag: (rowId: string, e: import("react").DragEvent<HTMLDivElement>) => void
  archiveListRow: (email: Email) => void
  deleteListRow: (email: Email) => void
  toggleStar: (id: string) => void
  toggleImportant: (id: string) => void
  openSwipeRowLabelSheet: (emailId: string) => void
  handleNavigateToLabel: (label: string) => void
  handleCategoryInboxTabClick: (tabId: string) => void
  closeViewIfShowingEmail: (emailId: string) => void
  restoreSnoozedRowToMailbox: (email: Email) => void
  handleEditScheduledMail: (id: string) => void
  requestArchiveScheduled: (id: string) => void | Promise<void>
  requestDeleteScheduled: (id: string) => void | Promise<void>
  requestToggleReadScheduled: (id: string, read: boolean) => void | Promise<void>
  requestSnoozeScheduled: (id: string) => void | Promise<void>
  requestRescheduleScheduled: (id: string, iso: string) => void | Promise<void>
  requestSendScheduledNow: (id: string) => void | Promise<void>
  requestSnoozeMailboxEmail: (email: Email) => void | Promise<void>
}

function EmailListRowInner(props: EmailListRowProps) {
  const {
    email,
    allEmails,
    emailById,
    listMailIndex,
    listRowExtras,
    starredEmails,
    importantEmails,
    readOverrides,
    conversationMode,
    savedThreadReplyDrafts,
    selectedEmails,
    selectedFolder,
    splitView,
    openMailId,
    isXs,
    isMd,
    density,
    mobileSelectionMode,
    touchListSwipeEnabled,
    openSwipeRowId,
    setOpenSwipeRowId,
    listRowLabelBgByTextLower,
    sidebarNav,
    rescheduleTarget,
    setRescheduleTarget,
    rescheduleDismissTimeoutsRef,
    scheduleReschedulePopoverDismiss,
    rowContextMenuOpenedAtRef,
    contextMenuTargetIdsRef,
    lastSelectionAnchorIdRef,
    setSelectedEmails,
    setLabelPickerQuery,
    labelPickerQuery,
    catalogLabels,
    resolveLabelVisual,
    getCatalogLabelPresence,
    toggleLabelOnEmails,
    addLabelToEmails,
    moveTargets,
    moveEmailsToTarget,
    cmScheduledRescheduleValue,
    setCmScheduledRescheduleValue,
    mailActions,
    setReadOverrides,
    onSelectFolder,
    toggleSelect,
    handleRowCheckboxClickCapture,
    handleRowActivate,
    startRowDrag,
    archiveListRow,
    deleteListRow,
    toggleStar,
    toggleImportant,
    openSwipeRowLabelSheet,
    handleNavigateToLabel,
    handleCategoryInboxTabClick,
    closeViewIfShowingEmail,
    restoreSnoozedRowToMailbox,
    handleEditScheduledMail,
    requestArchiveScheduled,
    requestDeleteScheduled,
    requestToggleReadScheduled,
    requestSnoozeScheduled,
    requestRescheduleScheduled,
    requestSendScheduledNow,
    requestSnoozeMailboxEmail,
  } = props


  const rowThreadId = threadStoreId(email)
  const isStarred =
    starredEmails.includes(rowThreadId) || email.starred
  const isImportant =
    importantEmails.includes(rowThreadId) || email.important
  const isSpam = email.spam === true
  const isDraft = email.labels?.includes("drafts") === true
  const hasThreadReplyDraft =
    savedThreadReplyDrafts[rowThreadId] !== undefined
  const showDraftBadge = isDraft || hasThreadReplyDraft
  const isRead = isListRowRead(
    email,
    readOverrides,
    emailById,
    conversationMode
  )
  const senderHoverEmail = resolveSenderEmail(email.sender, email.senderEmail)
  const threadMessageCount = conversationMode
    ? getThreadMessageCount(email)
    : 0
  const senderForSearch = email.sender.replace(/\s+/g, " ").trim()
  const isSelected = selectedEmails.includes(email.id)
  const isSplitActiveRow =
    splitView && openMailId === email.id
  const hasInvitation = email.hasInvitation === true
  const parsedInvitation =
    listRowExtras.invitationById.get(email.id) ?? null
  const attachmentList =
    listRowExtras.attachmentsById.get(email.id) ?? []
  const showAttachmentPills =
    attachmentList.length > 0 && (!isMd || density === "default")
  const showListPaperclip =
    attachmentList.length > 0 && isMd && density !== "default"
  const isCompactListRow = isMd && density === "compact"
  const listRowPadTop = !showAttachmentPills
    ? isCompactListRow
      ? "pt-0"
      : "pt-1"
    : isCompactListRow
      ? "pt-0"
      : "pt-0.5"
  const isScheduled = email.labels?.includes("scheduled") === true
  const contextTargetIds = contextMenuTargetIdsForRow(
    email.id,
    selectedEmails,
    selectedFolder,
    allEmails
  )
  const allContextTargetsScheduled =
    contextTargetIds.length > 0 &&
    contextTargetIds.every((id) =>
      listMailIndex.scheduledIds.has(id)
    )
  const scheduledCtxAnyUnread =
    allContextTargetsScheduled &&
    contextTargetIds.some((id) => {
      const em = listMailIndex.emailById.get(id)
      if (!em) return false
      return !(readOverrides[id] ?? em.read)
    })
  const isRescheduleOpenThisRow =
    rescheduleTarget?.id === email.id
  const spamRowHoverNoArchive = selectedFolder === "spam"
  const snoozedFolderRow = selectedFolder === "snoozed"

  return (
    <ContextMenu
    key={email.id}
    modal={false}
    onOpenChange={(open) => {
      if (open) {
        rowContextMenuOpenedAtRef.current = Date.now()
        setSelectedEmails((prev) => {
          const next = contextMenuTargetIdsForRow(
            email.id,
            prev,
            selectedFolder,
            allEmails
          )
          contextMenuTargetIdsRef.current = [...next]
          return next
        })
      } else {
        setLabelPickerQuery("")
      }
    }}
  >
    <ContextMenuTrigger asChild>
  <MailListSwipeRow
    enabled={touchListSwipeEnabled}
    emailId={email.id}
    isOpen={openSwipeRowId === email.id}
    onOpenChange={(open) => {
      if (open) setOpenSwipeRowId(email.id)
      else if (openSwipeRowId === email.id) setOpenSwipeRowId(null)
    }}
    onArchive={() => archiveListRow(email)}
    onDelete={() => deleteListRow(email)}
    onStar={() => toggleStar(email.id)}
    onLabel={() => openSwipeRowLabelSheet(email.id)}
  >
  <div
    data-email-row-id={email.id}
    data-split-active={isSplitActiveRow ? "" : undefined}
    aria-current={isSplitActiveRow ? "true" : undefined}
    draggable={!isXs}
    onDragStart={isXs ? undefined : (e) => startRowDrag(email.id, e)}
    onClick={() => {
      if (readXsMatches() && mobileSelectionMode) {
        toggleSelect(email.id)
        lastSelectionAnchorIdRef.current = email.id
        return
      }
      handleRowActivate(email)
    }}
    className={cn(
      "group relative z-0 w-full cursor-pointer pl-3 pr-2 py-2 transition-[background-color,box-shadow] duration-[50ms] ease-out",
      !splitView &&
        "md:flex md:gap-2 md:px-2 md:py-1.5",
      !splitView &&
        (isCompactListRow && !showAttachmentPills
          ? "md:items-center"
          : "md:items-start"),
      isCompactListRow && "md:!py-1 md:text-[13px]",
      isSplitActiveRow
        ? "z-[1] bg-mail-row-active-split shadow-[inset_3px_0_0_0_#669df6]"
        : isSelected
          ? "bg-mail-row-selected"
          : isRead
            ? "bg-mail-row-read"
            : "bg-mail-row-unread",
      !isSplitActiveRow &&
        "hover:z-1 hover:shadow-[inset_1px_0_0_#d2d5da,inset_-1px_0_0_#d2d5da,0_4px_10px_-3px_rgba(60,64,67,.16),0_2px_5px_0_rgba(60,64,67,.09)]"
    )}
  >
    {/* Compact < md */}
    <div
      className={cn(
        "flex w-full min-w-0 flex-col gap-0.5",
        !splitView && "md:hidden",
        mobileSelectionMode &&
          "max-sm:flex-row max-sm:items-center max-sm:gap-2"
      )}
    >
      {mobileSelectionMode && (
        <div
          className="flex shrink-0 self-center sm:hidden"
          onClick={(e) => e.stopPropagation()}
          onClickCapture={(e) => handleRowCheckboxClickCapture(email.id, e)}
        >
          <Checkbox
            className={listRowCheckboxClass(true)}
            checked={isSelected}
            onCheckedChange={() => {
              toggleSelect(email.id)
              lastSelectionAnchorIdRef.current = email.id
            }}
          />
        </div>
      )}
      <div
        className={cn(
          "flex min-w-0 flex-1 flex-col gap-0.5",
          mobileSelectionMode && "max-sm:pointer-events-none"
        )}
        data-selectable-text
      >
      <div className="flex w-full min-w-0 items-center gap-2">
        <div
          className="hidden shrink-0 items-center sm:flex"
          onClick={(e) => e.stopPropagation()}
          onClickCapture={(e) => handleRowCheckboxClickCapture(email.id, e)}
        >
          <Checkbox
            className={listRowCheckboxClass(false)}
            checked={isSelected}
            onCheckedChange={() => {
              toggleSelect(email.id)
              lastSelectionAnchorIdRef.current = email.id
            }}
          />
        </div>
        <div className="flex min-w-0 flex-1 items-center justify-between gap-2">
          <div className="flex min-w-0 flex-1 items-center gap-1">
            <button
              type="button"
              onClick={(e) => {
                e.stopPropagation()
                toggleImportant(email.id)
              }}
              className={cn(
                "flex h-7 w-7 shrink-0 cursor-pointer items-center justify-center rounded-full",
                isSpam
                  ? "text-[#d93025] hover:bg-[#d93025]/10 hover:text-[#b3261e]"
                  : "text-[#c2c2c2] hover:bg-black/4 hover:text-[#5f6368]"
              )}
              aria-label={
                isSpam
                  ? "Marqué comme spam"
                  : isImportant
                    ? "Retirer important"
                    : "Marquer important"
              }
            >
              <Icon
                icon={importantSignalIcon(isSpam, isImportant)}
                className={cn(
                  "size-4 shrink-0",
                  isSpam && "text-[#d93025]",
                  !isSpam &&
                    (isImportant ? "text-[#f4cc70]" : "text-[#c2c2c2]")
                )}
                aria-hidden
              />
            </button>
            {isScheduled && (
              <span
                className="flex h-7 w-6 shrink-0 items-center justify-center text-[#5f6368]"
                aria-hidden
              >
                <Send className="size-3.5" strokeWidth={2} />
              </span>
            )}
        {isScheduled ? (
          <span
            className={cn(
              "min-w-0 truncate text-sm",
              !isRead ? "font-semibold text-gray-900" : "font-normal text-gray-700"
            )}
          >
            À : {email.scheduledToName ?? email.sender}
          </span>
        ) : (
        <ContactHoverCard displayName={email.sender} email={senderHoverEmail}>
          <span
            className={cn(
              "min-w-0 truncate text-sm",
              !isRead ? "font-semibold text-gray-900" : "font-normal text-gray-700"
            )}
          >
            {showDraftBadge && (
              <span className="font-medium text-[#d93025]">Brouillon </span>
            )}
            {email.sender}
          </span>
        </ContactHoverCard>
        )}
            {threadMessageCount > 1 && (
              <span className="shrink-0 text-sm font-normal text-gray-500">
                {threadMessageCount}
              </span>
            )}
          </div>
          <div className="flex shrink-0 items-center gap-1">
            {(parsedInvitation || hasInvitation) && (
              <Icon
                icon={
                  parsedInvitation
                    ? VIDEO_CONFERENCE_LOGOS[
                        parsedInvitation.conferenceProvider
                      ]
                    : "mdi:calendar"
                }
                className="size-4 shrink-0 text-[#5f6368]"
                aria-label={
                  parsedInvitation
                    ? "Invitation visioconférence"
                    : "Invitation calendrier"
                }
              />
            )}
            {attachmentList.length > 0 && (
              <Paperclip
                className="size-4 shrink-0 text-[#5f6368]"
                strokeWidth={1.75}
                aria-label="Pièces jointes"
              />
            )}
            {listRowExtras.categoryTabsById.get(email.id) ? (
              <MailInboxCategoryTabIcons
                tabs={listRowExtras.categoryTabsById.get(email.id)!}
                onTabClick={handleCategoryInboxTabClick}
              />
            ) : null}
            <span
              className={cn(
                "shrink-0 text-sm font-semibold tabular-nums tracking-tight",
                !isRead ? "text-gray-900" : "text-gray-700"
              )}
            >
              {isScheduled ? (
                formatScheduledDateTimeDisplay(email.scheduledSendAt)
              ) : (
                <MailDateText iso={email.date} variant="list" />
              )}
            </span>
          </div>
        </div>
      </div>

      <div className={cn("flex min-w-0 flex-wrap items-center gap-1 sm:pl-6")}>
          {email.tag && (
            <span className="shrink-0 rounded bg-gray-200 px-1.5 py-0.5 text-xs text-gray-600 opacity-[0.92]">
              {email.tag}
            </span>
          )}
          <MailLabelPillStrip
            variant="list"
            labels={email.labels}
            labelBgByText={listRowLabelBgByTextLower}
            emailLabelToSidebarFolderId={sidebarNav.emailLabelToSidebarFolderId}
            getNavItemPrefs={sidebarNav.getNavItemPrefs}
            labelRows={sidebarNav.labelRows}
            onLabelNavigate={handleNavigateToLabel}
            currentFolderId={selectedFolder}
            folderTree={sidebarNav.folderTree}
          />
          <span
            className={cn(
              "min-w-0 flex-1 text-sm leading-snug line-clamp-1",
              !isRead ? "font-semibold text-gray-900" : "font-semibold text-[#202124]"
            )}
          >
            {email.subject}
          </span>
        </div>

        <div className={cn("flex min-w-0 items-start gap-1.5 sm:pl-6")}>
          <p className="min-w-0 flex-1 text-sm leading-snug text-[#5f6368] line-clamp-1">
            {email.preview}
          </p>
          <button
            type="button"
            onClick={(e) => {
              e.stopPropagation()
              toggleStar(email.id)
            }}
            className="mt-0.5 flex h-7 w-7 shrink-0 cursor-pointer items-center justify-center rounded-full text-[#c2c2c2] hover:bg-black/4 hover:text-[#5f6368]"
            aria-label={isStarred ? "Retirer des favoris" : "Marquer comme favori"}
          >
            <Star
              strokeWidth={isStarred ? 0 : 1.25}
              className={cn(
                "size-4",
                isStarred
                  ? "fill-[#f4cc70] stroke-none text-[#f4cc70]"
                  : "fill-transparent stroke-[#c2c2c2]"
              )}
            />
          </button>
        </div>
      </div>
    </div>

    {/* Desktop >= md */}
    <div
      className={cn(
        "hidden w-full items-start gap-2",
        !splitView && "md:flex"
      )}
    >
    <div className="flex shrink-0 items-center gap-2">
      <div
        className="flex shrink-0"
        onClick={(e) => e.stopPropagation()}
        onClickCapture={(e) => handleRowCheckboxClickCapture(email.id, e)}
      >
        <Checkbox
          className="size-4 min-h-4 min-w-4 shrink-0 rounded-[2.5px] border-[1.5px] border-[#c2c2c2] bg-transparent shadow-none dark:bg-transparent focus-visible:ring-[#c2c2c2]/30 data-[state=checked]:border-[#1a73e8] data-[state=checked]:bg-[#1a73e8] data-[state=checked]:text-white"
          checked={isSelected}
          onCheckedChange={() => {
            toggleSelect(email.id)
            lastSelectionAnchorIdRef.current = email.id
          }}
        />
      </div>

      <div className="flex items-center gap-0">
        <button
          type="button"
          onClick={(e) => {
            e.stopPropagation()
            toggleStar(email.id)
          }}
          className="flex h-7 w-7 shrink-0 cursor-pointer items-center justify-center rounded-full text-[#c2c2c2] hover:bg-black/4 hover:text-[#5f6368]"
          aria-label={isStarred ? "Retirer des favoris" : "Marquer comme favori"}
        >
          <Star
            strokeWidth={isStarred ? 0 : 1.25}
            className={cn(
              "size-4",
              isStarred
                ? "fill-[#f4cc70] stroke-none text-[#f4cc70]"
                : "fill-transparent stroke-[#c2c2c2]"
            )}
          />
        </button>

        <button
          type="button"
          onClick={(e) => {
            e.stopPropagation()
            toggleImportant(email.id)
          }}
          className={cn(
            "flex h-7 w-7 shrink-0 cursor-pointer items-center justify-center rounded-full",
            isSpam
              ? "text-[#d93025] hover:bg-[#d93025]/10 hover:text-[#b3261e]"
              : "text-[#c2c2c2] hover:bg-black/4 hover:text-[#5f6368]"
          )}
          aria-label={
            isSpam
              ? "Marqué comme spam"
              : isImportant
                ? "Retirer important"
                : "Marquer important"
          }
        >
          <Icon
            icon={importantSignalIcon(isSpam, isImportant)}
            className={cn(
              "size-4 shrink-0",
              isSpam && "text-[#d93025]",
              !isSpam &&
                (isImportant ? "text-[#f4cc70]" : "text-[#c2c2c2]")
            )}
            aria-hidden
          />
        </button>
        {isScheduled && (
          <span
            className="flex h-7 w-6 shrink-0 items-center justify-center text-[#5f6368]"
            aria-hidden
          >
            <Send className="size-3.5" strokeWidth={2} />
          </span>
        )}
      </div>
    </div>

    <div
      className={cn(
        "flex w-44 shrink-0 items-center gap-1 pl-2 lg:w-40",
        listRowPadTop,
        isCompactListRow && "min-h-7 leading-tight"
      )}
      data-selectable-text
    >
      {isScheduled ? (
        <span
          className={cn(
            "min-w-0 truncate text-sm leading-5",
            !isRead ? "font-semibold text-gray-900" : "text-gray-700"
          )}
        >
          À : {email.scheduledToName ?? email.sender}
        </span>
      ) : (
      <ContactHoverCard
        displayName={email.sender}
        email={senderHoverEmail}
        className="min-w-0 flex-1 truncate leading-5"
      >
        <span
          className={cn(
            "block truncate text-sm leading-5",
            !isRead ? "font-semibold text-gray-900" : "text-gray-700"
          )}
        >
          {showDraftBadge && (
            <span className="font-medium text-[#d93025]">Brouillon </span>
          )}
          {email.sender}
        </span>
      </ContactHoverCard>
      )}
      {threadMessageCount > 1 && (
        <span className="shrink-0 text-sm leading-5 text-gray-500">
          {threadMessageCount}
        </span>
      )}
    </div>

    <div
      className="flex min-w-0 flex-1 flex-col justify-start gap-0.5 px-2 pb-0.5"
      data-selectable-text
    >
      <div
        className={cn(
          "flex min-w-0 items-center gap-1",
          listRowPadTop,
          isCompactListRow && "leading-tight"
        )}
      >
        {email.tag && (
          <span className="shrink-0 rounded bg-gray-200 px-1.5 py-0.5 text-xs text-gray-600 opacity-[0.92]">
            {email.tag}
          </span>
        )}
        <MailLabelPillStrip
          variant="list"
          labels={email.labels}
          labelBgByText={listRowLabelBgByTextLower}
          emailLabelToSidebarFolderId={sidebarNav.emailLabelToSidebarFolderId}
          getNavItemPrefs={sidebarNav.getNavItemPrefs}
          labelRows={sidebarNav.labelRows}
          onLabelNavigate={handleNavigateToLabel}
          currentFolderId={selectedFolder}
          folderTree={sidebarNav.folderTree}
        />
        <span
          className={cn(
            "min-w-0 shrink truncate text-sm leading-5",
            !isRead ? "font-semibold text-gray-900" : "font-normal text-[#3c4043]"
          )}
        >
          {email.subject}
        </span>
        <span className="min-w-0 flex-1 truncate text-sm leading-5 text-gray-500">
          {email.preview}
        </span>
      </div>
      {showAttachmentPills && (
        <EmailListAttachmentRow emailId={email.id} attachments={attachmentList} />
      )}
    </div>

    <div
      className={cn(
        "flex shrink-0 flex-col items-end gap-1 pr-2 text-right md:max-w-[150px] md:min-w-0",
        listRowPadTop,
        isCompactListRow && !showAttachmentPills
          ? "self-center"
          : "self-start"
      )}
    >
      {isScheduled ? (
        <div className="relative flex w-full min-w-0 shrink-0 items-center justify-end">
          <span
            className={cn(
              "block max-w-full truncate text-sm font-semibold tabular-nums text-[#c65308]",
              "transition-opacity duration-[50ms] ease-out",
              isRescheduleOpenThisRow
                ? "opacity-0"
                : "opacity-100 group-hover:opacity-0"
            )}
          >
            {formatScheduledDateTimeDisplay(email.scheduledSendAt)}
          </span>
          <div
            className={cn(
              "pointer-events-none absolute right-0 top-1/2 z-[1] flex w-max -translate-y-1/2 flex-nowrap items-center gap-0.5 rounded-md py-0.5 pl-1 opacity-0 transition-opacity duration-[50ms] ease-out",
              listRowQuickHoverTrayToneClass(isSelected, isRead),
              isRescheduleOpenThisRow
                ? "pointer-events-auto opacity-100"
                : "group-hover:pointer-events-auto group-hover:opacity-100"
            )}
          >
            {!spamRowHoverNoArchive && (
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                  aria-label="Archiver"
                  onClick={(e) => {
                    e.stopPropagation()
                    void requestArchiveScheduled(email.id)
                  }}
                >
                  <Archive className="h-[18px] w-[18px]" strokeWidth={1.5} />
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">
                Archiver
              </TooltipContent>
            </Tooltip>
            )}
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                  aria-label="Supprimer"
                  onClick={(e) => {
                    e.stopPropagation()
                    void requestDeleteScheduled(email.id)
                  }}
                >
                  <Trash2 className="h-[18px] w-[18px]" strokeWidth={1.5} />
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">
                Supprimer
              </TooltipContent>
            </Tooltip>
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                  aria-label={isRead ? "Marquer comme non lu" : "Marquer comme lu"}
                  onClick={(e) => {
                    e.stopPropagation()
                    const next = !isRead
                    setReadOverrides((prev) => ({ ...prev, [email.id]: next }))
                    void requestToggleReadScheduled(email.id, next)
                  }}
                >
                  {isRead ? (
                    <Mail className="h-[18px] w-[18px]" strokeWidth={1.5} />
                  ) : (
                    <MailOpen className="h-[18px] w-[18px]" strokeWidth={1.5} />
                  )}
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">
                {isRead ? "Marquer comme non lu" : "Marquer comme lu"}
              </TooltipContent>
            </Tooltip>
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                  aria-label="Mettre en attente"
                  onClick={(e) => {
                    e.stopPropagation()
                    void requestSnoozeScheduled(email.id)
                  }}
                >
                  <Clock className="h-[18px] w-[18px]" strokeWidth={1.5} />
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">
                Mettre en attente
              </TooltipContent>
            </Tooltip>
            <Popover
              open={
                rescheduleTarget?.id === email.id &&
                rescheduleTarget.panelOpen
              }
              onOpenChange={(open) => {
                if (open) {
                  const pending =
                    rescheduleDismissTimeoutsRef.current.get(
                      email.id
                    )
                  if (pending) {
                    clearTimeout(pending)
                    rescheduleDismissTimeoutsRef.current.delete(
                      email.id
                    )
                  }
                  setRescheduleTarget({
                    id: email.id,
                    value: scheduledIsoToDatetimeLocalValue(
                      email.scheduledSendAt
                    ),
                    panelOpen: true,
                  })
                } else {
                  setRescheduleTarget((prev) =>
                    prev?.id === email.id
                      ? { ...prev, panelOpen: false }
                      : prev
                  )
                  scheduleReschedulePopoverDismiss(email.id)
                }
              }}
            >
              <Tooltip>
                <TooltipTrigger asChild>
                  <PopoverTrigger asChild>
                    <Button
                      type="button"
                      variant="ghost"
                      size="icon"
                      className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                      aria-label="Reprogrammer"
                      onClick={(e) => e.stopPropagation()}
                    >
                      <CalendarClock
                        className="h-[18px] w-[18px]"
                        strokeWidth={1.5}
                      />
                    </Button>
                  </PopoverTrigger>
                </TooltipTrigger>
                <TooltipContent side="bottom" className="text-xs">
                  Reprogrammer
                </TooltipContent>
              </Tooltip>
              <PopoverContent
                className="w-[min(100vw-2rem,280px)] p-3"
                align="end"
                side="bottom"
                sideOffset={6}
                collisionPadding={12}
                onClick={(e) => e.stopPropagation()}
              >
                <p className="mb-2 text-xs font-medium text-[#3c4043]">
                  Nouvelle date d&apos;envoi
                </p>
                <input
                  type="datetime-local"
                  className="mb-3 w-full rounded border border-[#dadce0] px-2 py-1.5 text-sm text-[#3c4043]"
                  value={
                    rescheduleTarget?.id === email.id
                      ? rescheduleTarget.value
                      : ""
                  }
                  onChange={(e) =>
                    setRescheduleTarget((prev) =>
                      prev?.id === email.id
                        ? {
                            ...prev,
                            value: e.target.value,
                            panelOpen: true,
                          }
                        : prev
                    )
                  }
                />
                <div className="flex justify-end gap-2">
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    className="h-8 text-xs"
                    onClick={() => {
                      setRescheduleTarget((prev) =>
                        prev?.id === email.id
                          ? { ...prev, panelOpen: false }
                          : prev
                      )
                      scheduleReschedulePopoverDismiss(email.id)
                    }}
                  >
                    Annuler
                  </Button>
                  <Button
                    type="button"
                    size="sm"
                    className="h-8 text-xs"
                    onClick={() => {
                      if (rescheduleTarget?.id !== email.id) return
                      const iso = parseDatetimeLocalToIso(
                        rescheduleTarget.value
                      )
                      if (!iso) return
                      void requestRescheduleScheduled(email.id, iso)
                      setRescheduleTarget((prev) =>
                        prev?.id === email.id
                          ? { ...prev, panelOpen: false }
                          : prev
                      )
                      scheduleReschedulePopoverDismiss(email.id)
                    }}
                  >
                    Valider
                  </Button>
                </div>
              </PopoverContent>
            </Popover>
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                  aria-label="Modifier le mail"
                  onClick={(e) => {
                    e.stopPropagation()
                    void handleEditScheduledMail(email.id)
                  }}
                >
                  <Pencil
                    className="h-[18px] w-[18px]"
                    strokeWidth={1.5}
                  />
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">
                Modifier le mail
              </TooltipContent>
            </Tooltip>
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                  aria-label="Envoyer maintenant"
                  onClick={(e) => {
                    e.stopPropagation()
                    void requestSendScheduledNow(email.id)
                  }}
                >
                  <Send
                    className="h-[18px] w-[18px]"
                    strokeWidth={1.5}
                  />
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">
                Envoyer maintenant
              </TooltipContent>
            </Tooltip>
          </div>
        </div>
      ) : (
        <div className="relative flex w-full min-w-0 shrink-0 items-center justify-end">
          <div
            className={cn(
              "flex min-w-0 max-w-full items-center justify-end gap-1.5 overflow-hidden",
              "transition-opacity duration-[50ms] ease-out",
              "group-hover:opacity-0"
            )}
          >
            {(parsedInvitation || hasInvitation) && (
              <Icon
                icon={
                  parsedInvitation
                    ? VIDEO_CONFERENCE_LOGOS[
                        parsedInvitation.conferenceProvider
                      ]
                    : "mdi:calendar"
                }
                className="size-[18px] shrink-0 text-[#5f6368]"
                aria-label={
                  parsedInvitation
                    ? "Invitation visioconférence"
                    : "Invitation calendrier"
                }
              />
            )}
            {listRowExtras.categoryTabsById.get(email.id) ? (
              <MailInboxCategoryTabIcons
                tabs={listRowExtras.categoryTabsById.get(email.id)!}
                onTabClick={handleCategoryInboxTabClick}
                iconClassName="size-[18px] shrink-0"
              />
            ) : null}
            {showListPaperclip && (
              <Paperclip
                className="size-[18px] shrink-0 text-[#5f6368]"
                strokeWidth={1.75}
                aria-label="Pièces jointes"
              />
            )}
            <span
              className={cn(
                "min-w-0 truncate text-sm tabular-nums",
                !isRead ? "font-semibold text-gray-900" : "text-gray-600"
              )}
            >
              <MailDateText iso={email.date} variant="list" />
            </span>
          </div>
          <div
            className={cn(
              "pointer-events-none absolute right-0 top-1/2 z-[1] flex w-max -translate-y-1/2 flex-nowrap items-center gap-0.5 rounded-md py-0.5 pl-1 opacity-0 transition-opacity duration-[50ms] ease-out",
              listRowQuickHoverTrayToneClass(isSelected, isRead),
              "group-hover:pointer-events-auto group-hover:opacity-100"
            )}
          >
            {!spamRowHoverNoArchive && (
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                  aria-label="Archiver"
                  onClick={(e) => {
                    e.stopPropagation()
                    mailActions.hideEmail(email.id)
                    closeViewIfShowingEmail(email.id)
                  }}
                >
                  <Archive className="h-[18px] w-[18px]" strokeWidth={1.5} />
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">
                Archiver
              </TooltipContent>
            </Tooltip>
            )}
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                  aria-label="Supprimer"
                  onClick={(e) => {
                    e.stopPropagation()
                    mailActions.hideEmail(email.id)
                    closeViewIfShowingEmail(email.id)
                  }}
                >
                  <Trash2 className="h-[18px] w-[18px]" strokeWidth={1.5} />
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">
                Supprimer
              </TooltipContent>
            </Tooltip>
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                  aria-label={isRead ? "Marquer comme non lu" : "Marquer comme lu"}
                  onClick={(e) => {
                    e.stopPropagation()
                    const next = !isRead
                    setReadOverrides((prev) => ({ ...prev, [email.id]: next }))
                  }}
                >
                  {isRead ? (
                    <Mail className="h-[18px] w-[18px]" strokeWidth={1.5} />
                  ) : (
                    <MailOpen className="h-[18px] w-[18px]" strokeWidth={1.5} />
                  )}
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">
                {isRead ? "Marquer comme non lu" : "Marquer comme lu"}
              </TooltipContent>
            </Tooltip>
            {spamRowHoverNoArchive && (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                    aria-label="Déplacer vers la boîte de réception"
                    onClick={(e) => {
                      e.stopPropagation()
                      mailActions.markNotSpam(email.id)
                      onSelectFolder?.("inbox")
                      closeViewIfShowingEmail(email.id)
                    }}
                  >
                    <InboxIcon
                      className="h-[18px] w-[18px]"
                      strokeWidth={1.5}
                    />
                  </Button>
                </TooltipTrigger>
                <TooltipContent side="bottom" className="text-xs">
                  Boîte de réception
                </TooltipContent>
              </Tooltip>
            )}
            {!spamRowHoverNoArchive &&
              (snoozedFolderRow ? (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                    aria-label={
                      email.id.startsWith("snz-")
                        ? "Déplacer vers la boîte de réception"
                        : "Remettre dans les mails planifiés"
                    }
                    onClick={(e) => {
                      e.stopPropagation()
                      restoreSnoozedRowToMailbox(email)
                    }}
                  >
                    <InboxIcon
                      className="h-[18px] w-[18px]"
                      strokeWidth={1.5}
                    />
                  </Button>
                </TooltipTrigger>
                <TooltipContent side="bottom" className="text-xs">
                  {email.id.startsWith("snz-")
                    ? "Boîte de réception"
                    : "Planifiés"}
                </TooltipContent>
              </Tooltip>
            ) : (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    className="h-8 w-8 shrink-0 text-[#444746] hover:bg-[#f1f3f4]"
                    aria-label="Mettre en attente"
                    onClick={(e) => {
                      e.stopPropagation()
                      void requestSnoozeMailboxEmail(email)
                      if (email.labels?.includes("snoozed")) return
                      mailActions.hideEmail(email.id)
                      closeViewIfShowingEmail(email.id)
                    }}
                  >
                    <Clock className="h-[18px] w-[18px]" strokeWidth={1.5} />
                  </Button>
                </TooltipTrigger>
                <TooltipContent side="bottom" className="text-xs">
                  Mettre en attente
                </TooltipContent>
              </Tooltip>
            ))}
          </div>
        </div>
      )}
    </div>
    </div>
  </div>
  </MailListSwipeRow>
    </ContextMenuTrigger>

    <ContextMenuContent
      onCloseAutoFocus={(e) => e.preventDefault()}
      onPointerDownOutside={(event) => {
        const native = event.detail.originalEvent
        if (
          native.pointerType === "mouse" &&
          native.button === 2 &&
          Date.now() - rowContextMenuOpenedAtRef.current < 450
        ) {
          event.preventDefault()
        }
      }}
      className={cn(
        cn(MAIL_MENU_SURFACE_WIDE_CLASS, "overflow-visible"),
        "[&_[data-slot=context-menu-item]]:gap-3 [&_[data-slot=context-menu-item]]:rounded-none [&_[data-slot=context-menu-item]]:px-3 [&_[data-slot=context-menu-item]]:py-2 [&_[data-slot=context-menu-item]]:text-sm",
        "[&_[data-slot=context-menu-item]:focus]:bg-[#f1f3f4] [&_[data-slot=context-menu-item]:focus]:text-[#3c4043]",
        "[&_[data-slot=context-menu-sub-trigger]]:gap-3 [&_[data-slot=context-menu-sub-trigger]]:rounded-none [&_[data-slot=context-menu-sub-trigger]]:px-3 [&_[data-slot=context-menu-sub-trigger]]:py-2 [&_[data-slot=context-menu-sub-trigger]]:text-sm",
        "[&_[data-slot=context-menu-sub-trigger]:focus]:bg-[#f1f3f4] [&_[data-slot=context-menu-sub-trigger]:focus]:text-[#3c4043]",
        "[&_[data-slot=context-menu-separator]]:mx-0 [&_[data-slot=context-menu-separator]]:my-1 [&_[data-slot=context-menu-separator]]:h-px [&_[data-slot=context-menu-separator]]:bg-[#eceff1]",
        "[&_[data-slot=context-menu-sub-content]]:min-w-[200px] [&_[data-slot=context-menu-sub-content]]:rounded-lg [&_[data-slot=context-menu-sub-content]]:border [&_[data-slot=context-menu-sub-content]]:border-border [&_[data-slot=context-menu-sub-content]]:bg-popover [&_[data-slot=context-menu-sub-content]]:shadow-lg"
      )}
    >
      {allContextTargetsScheduled ? (
        <>
          <ContextMenuItem
            onSelect={() => {
              const ids = [...contextMenuTargetIdsRef.current]
              void Promise.all(
                ids.map((id) => requestArchiveScheduled(id))
              )
            }}
          >
            <Archive
              strokeWidth={1.5}
              className="size-[18px] text-[#5f6368]"
            />
            Archiver
          </ContextMenuItem>
          <ContextMenuItem
            onSelect={() => {
              const ids = [...contextMenuTargetIdsRef.current]
              void Promise.all(
                ids.map((id) => requestDeleteScheduled(id))
              )
            }}
          >
            <Trash2
              strokeWidth={1.5}
              className="size-[18px] text-[#5f6368]"
            />
            Supprimer
          </ContextMenuItem>
          <ContextMenuItem
            onSelect={() => {
              const ids = [...contextMenuTargetIdsRef.current]
              const markRead = scheduledCtxAnyUnread
              setReadOverrides((prev) => {
                const next = { ...prev }
                for (const id of ids) next[id] = markRead
                return next
              })
              void Promise.all(
                ids.map((id) =>
                  requestToggleReadScheduled(id, markRead)
                )
              )
            }}
          >
            {scheduledCtxAnyUnread ? (
              <Mail
                strokeWidth={1.5}
                className="size-[18px] text-[#5f6368]"
              />
            ) : (
              <MailOpen
                strokeWidth={1.5}
                className="size-[18px] text-[#5f6368]"
              />
            )}
            {scheduledCtxAnyUnread
              ? "Marquer comme lu"
              : "Marquer comme non lu"}
          </ContextMenuItem>
          <ContextMenuItem
            onSelect={() => {
              const ids = [...contextMenuTargetIdsRef.current]
              void Promise.all(
                ids.map((id) => requestSnoozeScheduled(id))
              )
            }}
          >
            <Clock
              strokeWidth={1.5}
              className="size-[18px] text-[#5f6368]"
            />
            Mettre en attente
          </ContextMenuItem>
          <ContextMenuSeparator />
          <ContextMenuSub
            onOpenChange={(subOpen) => {
              if (!subOpen) return
              const ids = contextMenuTargetIdsRef.current
              const first = allEmails.find((e) => e.id === ids[0])
              setCmScheduledRescheduleValue(
                scheduledIsoToDatetimeLocalValue(
                  first?.scheduledSendAt
                )
              )
            }}
          >
            <ContextMenuSubTrigger className="[&>svg:last-child]:text-[#5f6368]">
              <CalendarClock
                strokeWidth={1.5}
                className="size-[18px] text-[#5f6368]"
              />
              Reprogrammer
            </ContextMenuSubTrigger>
            <ContextMenuSubContent
              className={cn(
                "min-w-[288px] rounded-lg border border-border bg-popover px-4 py-3.5 text-[#3c4043] shadow-lg"
              )}
            >
              <div
                className="flex flex-col gap-3.5"
                onPointerDown={(e) => e.stopPropagation()}
              >
                <p className="text-xs font-medium leading-snug text-[#3c4043]">
                  Nouvelle date d&apos;envoi
                  {contextTargetIds.length > 1
                    ? ` (${contextTargetIds.length} messages)`
                    : null}
                </p>
                <input
                  type="datetime-local"
                  className="w-full rounded border border-[#dadce0] px-2.5 py-1.5 text-sm text-[#3c4043]"
                  value={cmScheduledRescheduleValue}
                  onChange={(e) =>
                    setCmScheduledRescheduleValue(e.target.value)
                  }
                  onPointerDown={(e) => e.stopPropagation()}
                />
                <button
                  type="button"
                  className="rounded bg-[#0b57d0] px-3 py-1.5 text-xs font-medium text-white hover:bg-[#0842a0]"
                  onPointerDown={(e) => {
                    e.stopPropagation()
                    e.preventDefault()
                  }}
                  onClick={(e) => {
                    e.stopPropagation()
                    const iso = parseDatetimeLocalToIso(
                      cmScheduledRescheduleValue
                    )
                    if (!iso) return
                    const ids = [
                      ...contextMenuTargetIdsRef.current,
                    ]
                    void Promise.all(
                      ids.map((id) =>
                        requestRescheduleScheduled(id, iso)
                      )
                    )
                  }}
                >
                  Valider
                </button>
              </div>
            </ContextMenuSubContent>
          </ContextMenuSub>
          <ContextMenuItem
            disabled={contextTargetIds.length > 1}
            onSelect={() => {
              if (contextTargetIds.length !== 1) return
              void handleEditScheduledMail(contextTargetIds[0]!)
            }}
          >
            <Pencil
              strokeWidth={1.5}
              className="size-[18px] text-[#5f6368]"
            />
            Modifier le mail
          </ContextMenuItem>
          <ContextMenuItem
            onSelect={() => {
              const ids = [...contextMenuTargetIdsRef.current]
              void Promise.all(
                ids.map((id) => requestSendScheduledNow(id))
              )
            }}
          >
            <Send
              strokeWidth={1.5}
              className="size-[18px] text-[#5f6368]"
            />
            Envoyer maintenant
          </ContextMenuItem>
        </>
      ) : (
        <>
      <ContextMenuItem>
        <Reply strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        Répondre
      </ContextMenuItem>
      <ContextMenuItem>
        <ReplyAll strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        Répondre à tous
      </ContextMenuItem>
      <ContextMenuItem>
        <Forward strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        Transférer
      </ContextMenuItem>
      <ContextMenuItem>
        <Paperclip strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        Transférer en tant que pièce jointe
      </ContextMenuItem>

      <ContextMenuSeparator />

      <ContextMenuItem>
        <Archive strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        Archiver
      </ContextMenuItem>
      <ContextMenuItem>
        <Trash2 strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        Supprimer
      </ContextMenuItem>
      <ContextMenuItem
        onSelect={() => {
          const newRead = !isRead
          const ids = contextMenuTargetIdsRef.current
          setReadOverrides((prev) => {
            const next = { ...prev }
            for (const id of ids) {
              next[id] = newRead
            }
            return next
          })
        }}
      >
        {!isRead ? (
          <Mail strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        ) : (
          <MailOpen strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        )}
        {isRead ? "Marquer comme non lu" : "Marquer comme lu"}
      </ContextMenuItem>
      <ContextMenuItem>
        <Clock strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        Mettre en attente
      </ContextMenuItem>
      <ContextMenuItem>
        <ListTodo strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        Ajouter à Tasks
      </ContextMenuItem>

      <ContextMenuSeparator />

      <ContextMenuSub>
        <ContextMenuSubTrigger className="[&>svg:last-child]:text-[#5f6368]">
          <FolderInput strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
          Déplacer vers
        </ContextMenuSubTrigger>
        <ContextMenuSubContent
          className={cn(
            cn(MAIL_MENU_SURFACE_CLASS, "max-h-80 overflow-y-auto"),
            "[&_[data-slot=context-menu-item]]:gap-3 [&_[data-slot=context-menu-item]]:rounded-none [&_[data-slot=context-menu-item]]:px-3 [&_[data-slot=context-menu-item]]:py-2 [&_[data-slot=context-menu-item]]:text-sm",
            "[&_[data-slot=context-menu-item]:focus]:bg-[#f1f3f4]"
          )}
        >
          <MoveToContextMenuItems
            targets={moveTargets}
            onMoveTo={(targetId) => {
              moveEmailsToTarget(contextTargetIds, targetId)
              if (targetId !== "inbox") {
                setSelectedEmails((prev) => prev.filter((id) => !contextTargetIds.includes(id)))
              }
            }}
          />
        </ContextMenuSubContent>
      </ContextMenuSub>

      <ContextMenuSub>
        <ContextMenuSubTrigger className="[&>svg:last-child]:text-[#5f6368]">
          <Tag strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
          Ajouter le libellé
        </ContextMenuSubTrigger>
        <ContextMenuSubContent
          className={cn(
            "z-[100] flex max-h-72 min-w-[260px] flex-col overflow-hidden rounded-lg border border-border bg-popover p-0 py-0 text-[#3c4043] shadow-lg",
            "[&_[data-slot=context-menu-item]]:gap-3 [&_[data-slot=context-menu-item]]:rounded-none [&_[data-slot=context-menu-item]]:px-3 [&_[data-slot=context-menu-item]]:py-2 [&_[data-slot=context-menu-item]]:text-sm",
            "[&_[data-slot=context-menu-item]:focus]:bg-[#f1f3f4]"
          )}
        >
          <EmailLabelPickerBlock
            query={labelPickerQuery}
            onQueryChange={setLabelPickerQuery}
            catalogLabels={catalogLabels}
            resolveLabelVisual={resolveLabelVisual}
            Item={ContextMenuItem}
            getLabelPresence={(lab) =>
              getCatalogLabelPresence(contextTargetIds, lab)
            }
            onToggleCatalogLabel={(lab) =>
              toggleLabelOnEmails(contextTargetIds, lab)
            }
            onCreateLabel={(lab) => {
              addLabelToEmails(contextTargetIds, lab)
              setLabelPickerQuery("")
            }}
          />
        </ContextMenuSubContent>
      </ContextMenuSub>

      <ContextMenuItem>
        <VolumeX strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        Ignorer la conversation
      </ContextMenuItem>

      <ContextMenuSeparator />

      <ContextMenuItem title={`Recherche : ${senderForSearch}`}>
        <Search strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        <span className="min-w-0 truncate">
          Rech. e-mails de {senderForSearch}
        </span>
      </ContextMenuItem>

      <ContextMenuSeparator />

      <ContextMenuItem>
        <SquareArrowOutUpRight strokeWidth={1.5} className="size-[18px] text-[#5f6368]" />
        Ouvrir dans une nouvelle fenêtre
      </ContextMenuItem>
        </>
      )}
    </ContextMenuContent>
  </ContextMenu>
  )
}

export const EmailListRow = memo(EmailListRowInner)
