"use client"

import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import {
  Star,
  Reply,
  ReplyAll,
  Forward,
  MoreVertical,
  Printer,
  ExternalLink,
  ChevronDown,
  Info,
  TriangleAlert,
  Trash2,
  Mail,
  Ban,
  ShieldAlert,
  Fish,
  Flag,
  SlidersHorizontal,
  Languages,
  Download,
  Code2,
  MessageCircleWarning,
  HardDrive,
  File,
  FileText,
  Image as ImageIcon,
} from "lucide-react"
import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip"
import { cn } from "@/lib/utils"
import {
  avatarColor,
  cleanSenderName,
  senderInitial,
} from "@/lib/sender-display"
import { MailDateText } from "@/components/gmail/mail-date-text"
import type {
  Email,
  ConversationMessage,
  EmailAttachment,
  EmailAttachmentKind,
} from "@/lib/email-data"
import type { FolderTreeNode, LabelRowItem } from "@/lib/sidebar-nav-data"
import {
  attachmentPreviewTooltip,
  resolveAttachmentKind,
  shouldUseAttachmentPillsInPreview,
} from "@/lib/attachment-display"
import {
  useComposeActions,
  useComposeDrafts,
  useComposeWindows,
  DEFAULT_IDENTITIES,
  type ThreadComposeKind,
  type ComposeOpenPreset,
  savedThreadDraftToComposePreset,
} from "@/lib/compose-context"
import {
  buildThreadComposePreset,
  withTouchFullscreenComposePreset,
} from "@/lib/thread-compose-preset"
import { openConversationPrint } from "@/lib/print-conversation"
import { resolveParsedCalendarInvitation } from "@/lib/resolve-email-calendar-invitation"
import { ComposeWindow } from "@/components/gmail/compose-modal"
import { CalendarInvitationPreview } from "@/components/gmail/calendar-invitation-preview"
import { ContactHoverCard } from "./contact-hover-card"
import { MailLabelPillStrip } from "./mail-label-pills"

interface EmailViewProps {
  email: Email
  onToggleStar: (id: string) => void
  isStarred: boolean
  onNavigateToLabel?: (label: string) => void
  /** Message spam : bannière + pastille sujet ; bouton « non-spam » */
  onNotSpam?: () => void
  /** Si défini, les pastilles libellé dont la fonction retourne false sont masquées (préférences barre latérale). */
  showLabelChip?: (label: string) => boolean
  labelBgByText?: Map<string, string>
  emailLabelToSidebarFolderId?: Record<string, string>
  getNavItemPrefs?: (id: string) => { messages: string }
  folderTree?: FolderTreeNode[]
  labelRows?: readonly LabelRowItem[]
  /** Id dossier / libellé courant — masque la pastille du dossier actif (comme en liste). */
  currentFolderId?: string
}

const LABEL_DISPLAY_NAMES: Record<string, string> = {
  inbox: "Boîte de réception",
  starred: "Suivis",
  snoozed: "En attente",
  important: "Important",
  sent: "Messages envoyés",
  drafts: "Brouillons",
  spam: "Spam",
  trash: "Corbeille",
}

const MESSAGE_MORE_MENU_CLASS =
  "min-w-[280px] rounded-lg border border-[#dadce0] bg-white p-0 py-1 text-[#3c4043] shadow-lg [&_[data-slot=dropdown-menu-item]]:gap-3 [&_[data-slot=dropdown-menu-item]]:rounded-none [&_[data-slot=dropdown-menu-item]]:px-3 [&_[data-slot=dropdown-menu-item]]:py-2 [&_[data-slot=dropdown-menu-item]]:text-sm [&_[data-slot=dropdown-menu-item]:focus]:bg-[#f1f3f4] [&_[data-slot=dropdown-menu-separator]]:mx-0 [&_[data-slot=dropdown-menu-separator]]:my-1 [&_[data-slot=dropdown-menu-separator]]:bg-[#eceff1]"

/** Scroll zone du corps du message (preview remplit le panneau parent). */
const EMAIL_PREVIEW_SCROLL_CLASS =
  "min-h-0 flex-1 overflow-y-auto overflow-x-hidden overscroll-y-contain outline-none " +
  "[scrollbar-color:#9aa0a6_#ffffff] [scrollbar-width:auto] " +
  "[&::-webkit-scrollbar]:w-2.5 [&::-webkit-scrollbar]:border-0 [&::-webkit-scrollbar]:bg-white " +
  "[&::-webkit-scrollbar-track]:border-0 [&::-webkit-scrollbar-track]:bg-white [&::-webkit-scrollbar-track]:shadow-none " +
  "[&::-webkit-scrollbar-thumb]:rounded-none [&::-webkit-scrollbar-thumb]:border-0 [&::-webkit-scrollbar-thumb]:shadow-none " +
  "[&::-webkit-scrollbar-thumb]:bg-[#9aa0a6] hover:[&::-webkit-scrollbar-thumb]:bg-[#5f6368] " +
  "[&::-webkit-scrollbar-corner]:border-0 [&::-webkit-scrollbar-corner]:bg-white"

const REPLY_BAR_SURFACE_CLASS =
  "bg-[linear-gradient(to_bottom,rgba(255,255,255,0)_0%,#ffffff_0.75rem,#ffffff_100%)] pt-3"

/* ── Sandboxed iframe for HTML body ── */

function SandboxedContent({
  html,
  isSpam,
}: {
  html: string
  isSpam: boolean
}) {
  const iframeRef = useRef<HTMLIFrameElement>(null)
  const [height, setHeight] = useState(120)

  const sandboxValue = isSpam
    ? "allow-same-origin"
    : "allow-same-origin allow-popups"

  const injectContent = useCallback(() => {
    const iframe = iframeRef.current
    if (!iframe) return

    const doc = iframe.contentDocument
    if (!doc) return

    const cspMeta = isSpam
      ? `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:;">`
      : `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src https: data:;">`

    doc.open()
    doc.write(`<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  ${cspMeta}
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
      font-size: 14px;
      line-height: 1.6;
      color: #202124;
      padding: 0;
      overflow: hidden;
      word-wrap: break-word;
      overflow-wrap: break-word;
    }
    a { color: #1a73e8; }
    img { max-width: 100%; height: auto; }
    blockquote {
      border-left: 3px solid #dadce0;
      padding-left: 12px;
      margin: 8px 0;
      color: #5f6368;
    }
    pre, code {
      background: #f6f8fa;
      border-radius: 3px;
      font-size: 13px;
    }
    pre { padding: 12px; overflow-x: auto; }
    code { padding: 2px 6px; }
  </style>
</head>
<body>${html}</body>
</html>`)
    doc.close()

    const resizeObserver = new ResizeObserver(() => {
      const body = iframe.contentDocument?.body
      if (body) {
        setHeight(Math.max(60, body.scrollHeight + 2))
      }
    })

    if (doc.body) {
      resizeObserver.observe(doc.body)
      setHeight(Math.max(60, doc.body.scrollHeight + 2))
    }

    return () => resizeObserver.disconnect()
  }, [html, isSpam])

  useEffect(() => {
    const cleanup = injectContent()
    return () => cleanup?.()
  }, [injectContent])

  return (
    <iframe
      ref={iframeRef}
      sandbox={sandboxValue}
      title="Contenu du message"
      className="w-full border-0"
      style={{ height, display: "block" }}
      tabIndex={-1}
    />
  )
}

/* ── Sandboxed iframe for subject ── */

function SandboxedSubject({ text }: { text: string }) {
  const iframeRef = useRef<HTMLIFrameElement>(null)

  useEffect(() => {
    const iframe = iframeRef.current
    if (!iframe) return
    const doc = iframe.contentDocument
    if (!doc) return

    doc.open()
    doc.write(`<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline';">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: 'Google Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      font-size: 22px;
      line-height: 1.3;
      color: #202124;
      overflow: hidden;
      white-space: normal;
      word-wrap: break-word;
    }
  </style>
</head>
<body>${text.replace(/</g, "&lt;").replace(/>/g, "&gt;")}</body>
</html>`)
    doc.close()
  }, [text])

  return (
    <iframe
      ref={iframeRef}
      sandbox="allow-same-origin"
      title="Sujet du message"
      className="pointer-events-none w-full border-0"
      style={{ height: 32, display: "block" }}
      tabIndex={-1}
    />
  )
}

function MessageAttachmentCard({ name, kind }: { name: string; kind: EmailAttachmentKind }) {
  return (
    <>
      <div className="relative flex h-[132px] shrink-0 flex-col items-center justify-center bg-linear-to-b from-[#f8f9fa] to-[#eceff1]">
        {kind === "image" ? (
          <ImageIcon className="size-11 text-[#9aa0a6]" strokeWidth={1.25} aria-hidden />
        ) : kind === "pdf" ? (
          <div
            className="rounded border border-[#dadce0] bg-white px-4 py-5 shadow-sm"
            aria-hidden
          >
            <span className="text-[11px] font-bold leading-none text-[#d93025]">PDF</span>
          </div>
        ) : (
          <File className="size-11 text-[#9aa0a6]" strokeWidth={1.25} aria-hidden />
        )}
      </div>
      <div className="flex min-h-[38px] items-center gap-2 border-t border-[#eceff1] bg-[#f1f3f4] px-2 py-1.5">
        {kind === "pdf" ? (
          <FileText className="size-4 shrink-0 text-[#d93025]" strokeWidth={1.5} aria-hidden />
        ) : kind === "image" ? (
          <ImageIcon className="size-4 shrink-0 text-[#1a73e8]" strokeWidth={1.5} aria-hidden />
        ) : (
          <File className="size-4 shrink-0 text-[#5f6368]" strokeWidth={1.5} aria-hidden />
        )}
        <span className="min-w-0 flex-1 truncate text-xs leading-tight text-[#3c4043]">
          {name}
        </span>
      </div>
    </>
  )
}

function MessageAttachmentPill({
  name,
  kind,
  sizeBytes,
}: {
  name: string
  kind: EmailAttachmentKind
  sizeBytes?: number
}) {
  const tip = attachmentPreviewTooltip(name, sizeBytes)
  return (
    <Tooltip>
      <TooltipTrigger asChild>
        <button
          type="button"
          className="inline-flex max-w-[min(100%,320px)] min-w-0 shrink-0 items-center gap-2 rounded-full border border-[#dadce0] bg-[#f8f9fa] py-1.5 pl-2.5 pr-3 text-left text-sm text-[#3c4043] shadow-sm transition hover:border-[#bdc1c6] hover:bg-white hover:shadow focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#1a73e8]"
        >
          {kind === "pdf" ? (
            <FileText className="size-4 shrink-0 text-[#d93025]" strokeWidth={1.5} aria-hidden />
          ) : kind === "image" ? (
            <ImageIcon className="size-4 shrink-0 text-[#1a73e8]" strokeWidth={1.5} aria-hidden />
          ) : (
            <File className="size-4 shrink-0 text-[#5f6368]" strokeWidth={1.5} aria-hidden />
          )}
          <span className="min-w-0 truncate font-medium">{name}</span>
        </button>
      </TooltipTrigger>
      <TooltipContent side="bottom" className="max-w-xs whitespace-pre-line text-xs">
        {tip}
      </TooltipContent>
    </Tooltip>
  )
}

function MessageAttachmentsSection({ attachments }: { attachments: EmailAttachment[] }) {
  const n = attachments.length
  if (n === 0) return null

  const summary = n === 1 ? "Une pièce jointe" : `${n} pièces jointes`
  const asPills = shouldUseAttachmentPillsInPreview(attachments)

  return (
    <div className="border-t border-[#eceff1] px-4 pb-4 pl-[68px] pt-4">
      <div className="mb-3 flex min-w-0 flex-wrap items-center justify-between gap-x-3 gap-y-2">
        <div className="flex min-w-0 max-w-[min(100%,28rem)] items-center gap-1 text-sm text-[#5f6368]">
          <span className="min-w-0 truncate">
            {summary}
            <span aria-hidden> · </span>
            <span>Analysé par VirusTotal</span>
          </span>
          <Tooltip delayDuration={400}>
            <TooltipTrigger asChild>
              <button
                type="button"
                className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-[#5f6368] hover:bg-black/6"
                aria-label="Informations sur l'analyse VirusTotal des pièces jointes"
              >
                <Info className="size-4" strokeWidth={1.75} />
              </button>
            </TooltipTrigger>
            <TooltipContent side="bottom" className="max-w-xs text-xs">
              VirusTotal analyse les pièces jointes et les compare à une base de signatures pour
              repérer les virus et logiciels malveillants.
            </TooltipContent>
          </Tooltip>
        </div>
        <button
          type="button"
          className="flex shrink-0 items-center gap-2 rounded-md py-1 pl-1 pr-2 text-sm font-medium text-[#1a73e8] hover:bg-[#f6f9fe]"
          aria-label="Ajouter à UltiDrive"
        >
          <HardDrive className="size-[18px] shrink-0" strokeWidth={1.5} aria-hidden />
          Ajouter à UltiDrive
        </button>
      </div>

      <div
        className={
          asPills
            ? "flex flex-wrap gap-2 pb-1"
            : "flex flex-nowrap gap-3 overflow-x-auto overflow-y-hidden pb-1 [-webkit-overflow-scrolling:touch]"
        }
        role="list"
        aria-label="Pièces jointes"
      >
        {attachments.map((att, index) => {
          const kind = resolveAttachmentKind(att.name, att.kind)
          const tip = attachmentPreviewTooltip(att.name, att.sizeBytes)
          if (asPills) {
            return (
              <div key={`${att.name}-${index}`} className="shrink-0" role="listitem">
                <MessageAttachmentPill name={att.name} kind={kind} sizeBytes={att.sizeBytes} />
              </div>
            )
          }
          return (
            <div key={`${att.name}-${index}`} className="shrink-0" role="listitem">
              <Tooltip>
                <TooltipTrigger asChild>
                  <button
                    type="button"
                    className="flex w-[200px] flex-col overflow-hidden rounded border border-[#dadce0] bg-white text-left shadow-sm transition hover:border-[#bdc1c6] hover:shadow-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#1a73e8]"
                  >
                    <MessageAttachmentCard name={att.name} kind={kind} />
                  </button>
                </TooltipTrigger>
                <TooltipContent side="bottom" className="max-w-xs whitespace-pre-line text-xs">
                  {tip}
                </TooltipContent>
              </Tooltip>
            </div>
          )
        })}
      </div>
    </div>
  )
}

/* ── Collapsed conversation message (accordion header) ── */

function CollapsedMessage({
  message,
  onClick,
}: {
  message: ConversationMessage
  onClick: () => void
}) {
  const name = cleanSenderName(message.sender)
  const color = avatarColor(name)

  return (
    <div
      role="button"
      tabIndex={0}
      onClick={onClick}
      onKeyDown={(e) => {
        if (e.key === "Enter" || e.key === " ") {
          e.preventDefault()
          onClick()
        }
      }}
      className="group flex w-full cursor-pointer items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-[#f6f9fe]"
    >
      <div
        className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full text-sm font-bold text-white"
        style={{ backgroundColor: color }}
      >
        {senderInitial(name)}
      </div>
      <div className="min-w-0 flex-1 flex flex-col gap-1" data-selectable-text>
        <div className="flex min-w-0 items-center justify-between gap-2">
          <ContactHoverCard displayName={message.sender} email={message.senderEmail} className="min-w-0">
            <span className="truncate text-sm font-semibold text-[#202124]">{name}</span>
          </ContactHoverCard>
          <div className="flex shrink-0 items-center gap-1">
            <MailDateText
              iso={message.date}
              variant="preview"
              className="text-xs text-[#5f6368]"
            />
            <Star
              strokeWidth={1.25}
              className="ml-1 size-4 fill-transparent stroke-[#c2c2c2]"
            />
          </div>
        </div>
        <p className="min-w-0 truncate text-sm leading-snug text-[#5f6368]">{message.preview}</p>
      </div>
    </div>
  )
}

/* ── Expanded message card (full body) ── */

function ExpandedMessage({
  sender,
  senderEmail,
  dateIso,
  body,
  isSpam,
  isLast,
  starred,
  attachments = [],
  onToggleStar,
  onCollapse,
  onPrintConversation,
}: {
  sender: string
  senderEmail: string
  dateIso: string
  body: string
  isSpam: boolean
  isLast: boolean
  starred: boolean
  attachments?: EmailAttachment[]
  onToggleStar?: () => void
  onCollapse?: () => void
  onPrintConversation?: () => void
}) {
  const [showDetails, setShowDetails] = useState(false)
  const name = cleanSenderName(sender)

  return (
    <div>
      {/* Sender row */}
      <div
        className={cn("flex items-start gap-3 px-4 py-3", !isLast && "cursor-pointer")}
        onClick={!isLast ? onCollapse : undefined}
      >
        {isSpam ? (
          <div
            className="flex h-10 w-10 shrink-0 self-start items-center justify-center rounded-full bg-[#e8eaed] text-[#e8710a]"
            aria-label="Expéditeur ou message suspect (spam)"
          >
            <TriangleAlert className="size-[22px]" strokeWidth={2} aria-hidden />
          </div>
        ) : (
          <div
            className="flex h-10 w-10 shrink-0 self-start items-center justify-center rounded-full text-sm font-bold text-white"
            style={{ backgroundColor: avatarColor(name) }}
          >
            {senderInitial(name)}
          </div>
        )}

        <div className="min-w-0 flex-1 flex flex-col gap-1" data-selectable-text>
          <div className="min-w-0 truncate text-sm leading-snug">
            <ContactHoverCard
              displayName={sender}
              email={senderEmail}
              onTriggerClick={!isLast ? (e) => e.stopPropagation() : undefined}
              className="inline min-w-0 max-w-full align-baseline"
            >
              <span className="font-semibold text-[#202124]">{name}</span>
              <span className="text-[#5f6368]"> &lt;{senderEmail}&gt;</span>
            </ContactHoverCard>
          </div>

          <div className="flex items-center gap-1">
            <button
              type="button"
              className="flex items-center gap-0.5 text-xs text-[#5f6368] hover:text-[#202124]"
              onClick={(e) => {
                e.stopPropagation()
                setShowDetails(!showDetails)
              }}
            >
              à moi
              <ChevronDown className={cn("h-3 w-3 transition-transform", showDetails && "rotate-180")} />
            </button>
          </div>

          {showDetails && (
            <div className="mt-1 space-y-0.5 text-xs text-[#5f6368]">
              <p>de : <span className="text-[#3c4043]">{name} &lt;{senderEmail}&gt;</span></p>
              <p>à : <span className="text-[#3c4043]">moi</span></p>
              <p>
                date :{" "}
                <MailDateText
                  iso={dateIso}
                  variant="detail"
                  className="text-[#3c4043]"
                />
              </p>
              {isSpam && (
                <p className="text-[#d93025]">sécurité : ce message est marqué comme spam — les images et appels externes sont bloqués</p>
              )}
            </div>
          )}
        </div>

        <div className="flex shrink-0 self-start items-center gap-1 pt-0.5">
          <MailDateText
            iso={dateIso}
            variant="preview"
            className="text-xs text-[#5f6368]"
          />

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

          {!onToggleStar && (
            <Star strokeWidth={1.25} className="ml-1 size-4 fill-transparent stroke-[#c2c2c2]" />
          )}

          <Tooltip delayDuration={400}>
            <TooltipTrigger asChild>
              <Button
                variant="ghost"
                size="icon"
                className="h-8 w-8 text-[#5f6368] hover:bg-[#f1f3f4]"
                aria-label="Répondre"
                onClick={(e) => e.stopPropagation()}
              >
                <Reply className="h-[18px] w-[18px]" strokeWidth={1.5} />
              </Button>
            </TooltipTrigger>
            <TooltipContent side="bottom" className="text-xs">Répondre</TooltipContent>
          </Tooltip>

          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button
                variant="ghost"
                size="icon"
                className="h-8 w-8 text-[#5f6368] hover:bg-[#f1f3f4]"
                aria-label="Plus d'actions"
                onClick={(e) => e.stopPropagation()}
              >
                <MoreVertical className="h-[18px] w-[18px]" strokeWidth={1.5} />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent
              align="end"
              sideOffset={4}
              className={MESSAGE_MORE_MENU_CLASS}
            >
              <DropdownMenuItem>
                <Reply className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Répondre
              </DropdownMenuItem>
              <DropdownMenuItem>
                <Forward className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Transférer
              </DropdownMenuItem>
              <DropdownMenuSeparator />
              <DropdownMenuItem>
                <Trash2 className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Supprimer
              </DropdownMenuItem>
              <DropdownMenuItem>
                <Mail className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Marquer comme non lus à partir d&apos;ici
              </DropdownMenuItem>
              <DropdownMenuSeparator />
              <DropdownMenuItem>
                <Ban className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Bloquer « {name} »
              </DropdownMenuItem>
              <DropdownMenuItem>
                <ShieldAlert className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Signaler comme spam
              </DropdownMenuItem>
              <DropdownMenuItem>
                <Fish className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Signaler comme hameçonnage
              </DropdownMenuItem>
              <DropdownMenuItem>
                <Flag className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Signaler un contenu illégal
              </DropdownMenuItem>
              <DropdownMenuSeparator />
              <DropdownMenuItem>
                <SlidersHorizontal className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Filtrer les messages similaires
              </DropdownMenuItem>
              <DropdownMenuItem>
                <Languages className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Traduire
              </DropdownMenuItem>
              <DropdownMenuItem
                onSelect={() => {
                  onPrintConversation?.()
                }}
              >
                <Printer className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Imprimer
              </DropdownMenuItem>
              <DropdownMenuItem>
                <Download className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Télécharger le message
              </DropdownMenuItem>
              <DropdownMenuItem>
                <Code2 className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Afficher l&apos;original
              </DropdownMenuItem>
              <DropdownMenuItem>
                <MessageCircleWarning className="size-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Partager pour aider à améliorer Google
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      </div>

      {/* Body */}
      <div
        className={cn(
          "px-4 pl-[68px]",
          attachments.length > 0 ? "pb-0" : "pb-4"
        )}
        data-selectable-text
      >
        <SandboxedContent html={body} isSpam={isSpam} />
      </div>

      {attachments.length > 0 && (
        <MessageAttachmentsSection attachments={attachments} />
      )}
    </div>
  )
}

/* ── Spam explainer (preview) ── */

function SpamWhyBanner({ onNotSpam }: { onNotSpam?: () => void }) {
  return (
    <div className="mx-6 mb-4 flex items-start gap-3 rounded-lg border border-[#e8eaed] bg-[#f1f3f4] px-4 py-3.5">
      <div className="min-w-0 flex-1 space-y-3">
        <p className="text-sm leading-snug text-[#3c4043]">
          <span className="font-medium text-[#202124]">Pourquoi ce message est-il dans le spam ?</span>{" "}
          Ce message est semblable à des messages identifiés comme spam par le passé.
        </p>
        {onNotSpam && (
          <button
            type="button"
            onClick={onNotSpam}
            className="rounded-md border border-[#dadce0] bg-white px-4 py-2 text-sm font-medium text-[#1a73e8] shadow-sm transition-colors hover:bg-[#f6f9fe]"
          >
            Signaler comme non-spam
          </button>
        )}
      </div>
      <Tooltip>
        <TooltipTrigger asChild>
          <button
            type="button"
            className="mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-[#5f6368] hover:bg-black/6"
            aria-label="En savoir plus sur le filtre anti-spam"
          >
            <Info className="h-[18px] w-[18px]" strokeWidth={1.75} />
          </button>
        </TooltipTrigger>
        <TooltipContent side="left" className="max-w-xs text-xs">
          Les filtres peuvent se tromper. Si le message est légitime, signalez-le comme non-spam pour
          l&apos;améliorer.
        </TooltipContent>
      </Tooltip>
    </div>
  )
}

/* ── Main EmailView component ── */

export function EmailView({
  email,
  onToggleStar,
  isStarred,
  onNavigateToLabel,
  onNotSpam,
  showLabelChip,
  labelBgByText,
  emailLabelToSidebarFolderId = {},
  getNavItemPrefs = () => ({ messages: "show" }),
  folderTree,
  labelRows,
  currentFolderId,
}: EmailViewProps) {
  const conversation = email.conversation ?? []
  const hasConversation = conversation.length > 0
  const isSpamMessage = email.spam === true

  // Track which conversation messages are expanded (by index).
  // By default all previous messages are collapsed, only the last (main) is expanded.
  const [expandedIds, setExpandedIds] = useState<Set<string>>(new Set())

  const toggleExpanded = (msgId: string) => {
    setExpandedIds((prev) => {
      const next = new Set(prev)
      if (next.has(msgId)) {
        next.delete(msgId)
      } else {
        next.add(msgId)
      }
      return next
    })
  }

  const mainSenderName = cleanSenderName(email.sender)
  const mainSenderAddr = email.senderEmail || `${mainSenderName.toLowerCase().replace(/\s+/g, ".")}@example.com`

  const { composeWindows } = useComposeWindows()
  const { savedThreadReplyDrafts } = useComposeDrafts()
  const { openComposeWithInitial } = useComposeActions()
  const inlineCompose = useMemo(
    () =>
      composeWindows.find(
        (c) => c.placement === "inline" && c.threadEmailId === email.id
      ),
    [composeWindows, email.id]
  )

  const mainMessageAttachments = useMemo((): EmailAttachment[] => {
    if (email.attachments && email.attachments.length > 0) return email.attachments
    if (email.hasAttachment) return [{ name: "Pièce jointe", kind: "other" }]
    return []
  }, [email.attachments, email.hasAttachment])

  const savedThreadDraft = savedThreadReplyDrafts[email.id]
  const hasInlineForThread = Boolean(inlineCompose)
  const showReplyForwardBar = !inlineCompose

  const previewScrollRef = useRef<HTMLDivElement>(null)
  const threadComposeAnchorRef = useRef<HTMLDivElement>(null)

  const scrollThreadComposeIntoView = useCallback(() => {
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        threadComposeAnchorRef.current?.scrollIntoView({
          behavior: "smooth",
          block: "end",
          inline: "nearest",
        })
      })
    })
  }, [])

  const openThreadCompose = useCallback(
    (preset: ComposeOpenPreset) => {
      const resolved = withTouchFullscreenComposePreset(preset)
      openComposeWithInitial(resolved)
      if (resolved.placement === "inline") {
        scrollThreadComposeIntoView()
      }
    },
    [openComposeWithInitial, scrollThreadComposeIntoView]
  )

  useEffect(() => {
    if (!savedThreadDraft || hasInlineForThread) return
    openThreadCompose(savedThreadDraftToComposePreset(savedThreadDraft))
  }, [
    email.id,
    savedThreadDraft,
    hasInlineForThread,
    openThreadCompose,
  ])

  const startThreadCompose = useCallback(
    (kind: ThreadComposeKind) => {
      openThreadCompose(buildThreadComposePreset(email, kind))
    },
    [email, openThreadCompose]
  )

  const selfIdentity = DEFAULT_IDENTITIES[0]
  const selfName = cleanSenderName(selfIdentity.name)

  const calendarInvitation = useMemo(
    () => resolveParsedCalendarInvitation(email),
    [email]
  )

  return (
    <TooltipProvider delayDuration={400}>
      <div className="flex min-h-0 min-w-0 flex-1 flex-col">
        <div ref={previewScrollRef} className={EMAIL_PREVIEW_SCROLL_CLASS}>
        {/* Subject header */}
        <div className="flex items-start gap-3 px-6 py-4">
          <div className="min-w-0 flex-1">
            <div className="flex flex-wrap items-center gap-2">
              <SandboxedSubject text={email.subject} />
              {labelBgByText && onNavigateToLabel ? (
                <MailLabelPillStrip
                  variant="header"
                  labels={email.labels ?? ["inbox"]}
                  labelBgByText={labelBgByText}
                  emailLabelToSidebarFolderId={emailLabelToSidebarFolderId}
                  getNavItemPrefs={getNavItemPrefs}
                  labelRows={labelRows}
                  folderTree={folderTree}
                  currentFolderId={currentFolderId}
                  onLabelNavigate={onNavigateToLabel}
                  showLabel={showLabelChip}
                  resolveDisplayName={(lab) => LABEL_DISPLAY_NAMES[lab] ?? lab}
                  showRemoveOnPills
                  spamChip={
                    isSpamMessage && onNotSpam
                      ? { onNotSpam }
                      : undefined
                  }
                />
              ) : null}
            </div>
          </div>
          <div className="flex shrink-0 items-center gap-1">
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className="h-8 w-8 text-[#5f6368] hover:bg-[#f1f3f4]"
                  aria-label="Imprimer"
                  onClick={() => openConversationPrint(email)}
                >
                  <Printer className="h-[18px] w-[18px]" strokeWidth={1.5} />
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">Imprimer tout</TooltipContent>
            </Tooltip>
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  variant="ghost"
                  size="icon"
                  className="h-8 w-8 text-[#5f6368] hover:bg-[#f1f3f4]"
                  aria-label="Ouvrir dans une nouvelle fenêtre"
                >
                  <ExternalLink className="h-[18px] w-[18px]" strokeWidth={1.5} />
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">Dans une nouvelle fenêtre</TooltipContent>
            </Tooltip>
          </div>
        </div>

        {calendarInvitation ? (
          <CalendarInvitationPreview invitation={calendarInvitation} />
        ) : null}

        {isSpamMessage && <SpamWhyBanner onNotSpam={onNotSpam} />}

        {/* Conversation messages */}
        {/* Previous messages in conversation */}
        {hasConversation && conversation.map((msg) => {
          const isExpanded = expandedIds.has(msg.id)

          if (isExpanded) {
            return (
              <div key={msg.id} className="border-b border-[#eceff1]">
                <ExpandedMessage
                  sender={msg.sender}
                  senderEmail={msg.senderEmail}
                  dateIso={msg.date}
                  body={msg.body}
                  isSpam={false}
                  isLast={false}
                  starred={false}
                  attachments={msg.attachments ?? []}
                  onCollapse={() => toggleExpanded(msg.id)}
                  onPrintConversation={() => openConversationPrint(email)}
                />
              </div>
            )
          }

          return (
            <div key={msg.id} className="border-b border-[#eceff1]">
              <CollapsedMessage
                message={msg}
                onClick={() => toggleExpanded(msg.id)}
              />
            </div>
          )
        })}

        {/* Last / main message — always expanded */}
        <ExpandedMessage
          sender={mainSenderName}
          senderEmail={mainSenderAddr}
          dateIso={email.date}
          body={email.body || `<p style="color:#5f6368;">${email.preview}</p>`}
          isSpam={email.spam === true}
          isLast={true}
          starred={isStarred}
          attachments={mainMessageAttachments}
          onToggleStar={() => onToggleStar(email.id)}
          onPrintConversation={() => openConversationPrint(email)}
        />

        {showReplyForwardBar ? (
            <div
              className={cn(
                "sticky bottom-0 z-10 mt-4 flex flex-wrap items-center gap-x-3 gap-y-2 px-4 pb-6 pl-[68px]",
                REPLY_BAR_SURFACE_CLASS
              )}
            >
              <button
                type="button"
                onClick={() => startThreadCompose("reply")}
                className="inline-flex shrink-0 items-center gap-2 whitespace-nowrap rounded-full border border-[#dadce0] bg-white px-6 py-2.5 text-sm font-medium text-[#3c4043] shadow-sm transition-shadow hover:bg-[#f6f9fe] hover:shadow-md"
              >
                <Reply className="h-[18px] w-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Répondre
              </button>
              <button
                type="button"
                onClick={() => startThreadCompose("replyAll")}
                className="inline-flex shrink-0 items-center gap-2 whitespace-nowrap rounded-full border border-[#dadce0] bg-white px-6 py-2.5 text-sm font-medium text-[#3c4043] shadow-sm transition-shadow hover:bg-[#f6f9fe] hover:shadow-md"
              >
                <ReplyAll className="h-[18px] w-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Répondre à tous
              </button>
              <button
                type="button"
                onClick={() => startThreadCompose("forward")}
                className="inline-flex shrink-0 items-center gap-2 whitespace-nowrap rounded-full border border-[#dadce0] bg-white px-6 py-2.5 text-sm font-medium text-[#3c4043] shadow-sm transition-shadow hover:bg-[#f6f9fe] hover:shadow-md"
              >
                <Forward className="h-[18px] w-[18px] shrink-0 text-[#5f6368]" strokeWidth={1.5} />
                Transférer
              </button>
            </div>
        ) : null}

        {inlineCompose ? (
          <div ref={threadComposeAnchorRef} className="mt-6 px-4 pb-6 pl-[68px]">
              <div className="flex items-start gap-3">
                <div
                  className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full text-sm font-bold text-white"
                  style={{ backgroundColor: avatarColor(selfName) }}
                  aria-hidden
                >
                  {senderInitial(selfName)}
                </div>
                <div className="min-w-0 flex-1">
                  <ComposeWindow
                    key={inlineCompose.id}
                    compose={inlineCompose}
                    threadSourceEmail={email}
                  />
                </div>
              </div>
            </div>
        ) : null}

        </div>
      </div>
    </TooltipProvider>
  )
}
