"use client"

import {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react"
import { Reply, ReplyAll, Forward } from "lucide-react"
import {
  TooltipProvider,
} from "@/components/ui/tooltip"
import { cn } from "@/lib/utils"
import {
  avatarColor,
  cleanSenderName,
  senderInitial,
} from "@/lib/sender-display"
import type { ApiMessageSummary, ApiMessageFull } from "@/lib/api/types"
import type { Email, EmailAttachment } from "@/lib/email-data"
import type { FolderTreeNode, LabelRowItem } from "@/lib/sidebar-nav-data"
import { useMessage, useThread } from "@/lib/api/hooks/use-mail-queries"
import {
  useToggleStar,
  useMarkRead,
  useUpdateFlags,
  useUpdateLabels,
} from "@/lib/api/hooks/use-mail-mutations"
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 { EmailViewSubjectHeader } from "./email-view/email-view-header"
import {
  MAIL_PREVIEW_SCROLL_CLASS,
  MAIL_REPLY_BAR_CLASS,
  MAIL_REPLY_BUTTON_CLASS,
} from "@/lib/mail-chrome-classes"
import {
  CollapsedMessage,
  ExpandedMessage,
  SpamWhyBanner,
} from "@/components/gmail/email-view/email-view-messages"

function apiToLegacyEmail(
  msg: ApiMessageSummary,
  full?: ApiMessageFull | null,
  thread?: ApiMessageFull[] | null
): Email {
  const senderName = msg.from[0]?.name ?? ""
  return {
    id: msg.id,
    sender: senderName,
    senderEmail: msg.from[0]?.address,
    subject: msg.subject,
    preview: msg.snippet,
    body: full?.body_html ?? full?.body_text,
    date: msg.date,
    read: msg.flags.includes("read"),
    starred: msg.flags.includes("starred"),
    important: msg.flags.includes("important"),
    spam: msg.flags.includes("spam") || msg.labels.includes("spam"),
    labels: msg.labels,
    hasAttachment: msg.has_attachments,
    conversation: thread
      ?.filter((m) => m.id !== msg.id)
      .map((m) => ({
        id: m.id,
        sender: m.from[0]?.name ?? "",
        senderEmail: m.from[0]?.address ?? "",
        date: m.date,
        body: m.body_html ?? m.body_text ?? "",
        preview: m.snippet,
      })),
  }
}

interface EmailViewProps {
  email: ApiMessageSummary
  onNavigateToLabel?: (label: string) => void
  showLabelChip?: (label: string) => boolean
  labelBgByText?: Map<string, string>
  emailLabelToSidebarFolderId?: Record<string, string>
  getNavItemPrefs?: (id: string) => { messages: string }
  folderTree?: FolderTreeNode[]
  labelRows?: readonly LabelRowItem[]
  currentFolderId?: string
  isSingleMessageView?: boolean
}

export function EmailView({
  email,
  onNavigateToLabel,
  showLabelChip,
  labelBgByText,
  emailLabelToSidebarFolderId = {},
  getNavItemPrefs = () => ({ messages: "show" }),
  folderTree,
  labelRows,
  currentFolderId,
  isSingleMessageView = false,
}: EmailViewProps) {
  const { data: fullMessage } = useMessage(email.id)
  const { data: threadMessages } = useThread(email.thread_id ?? null)

  const toggleStar = useToggleStar()
  const markRead = useMarkRead()
  const updateFlags = useUpdateFlags()
  const updateLabels = useUpdateLabels()

  const flags = fullMessage?.flags ?? email.flags
  const isStarred = flags.includes("starred")
  const isSpam = flags.includes("spam") || email.labels.includes("spam")

  const initialFlagsRef = useRef(flags)
  useEffect(() => {
    initialFlagsRef.current = email.flags
  }, [email.id, email.flags])

  useEffect(() => {
    if (!initialFlagsRef.current.includes("read")) {
      markRead.mutate({ id: email.id, flags: initialFlagsRef.current })
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [email.id])

  const body =
    fullMessage?.body_html ??
    fullMessage?.body_text ??
    `<p style="color:var(--muted-foreground);">${email.snippet}</p>`

  const [showFullThread, setShowFullThread] = useState(false)

  const priorMessages = useMemo(() => {
    if (!threadMessages) return []
    return threadMessages.filter((m) => m.id !== email.id)
  }, [threadMessages, email.id])

  const priorCount = priorMessages.length
  const showRepliesCta =
    isSingleMessageView && !showFullThread && priorCount > 0

  const conversation =
    isSingleMessageView && !showFullThread ? [] : priorMessages
  const hasConversation = conversation.length > 0

  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.from[0]?.name ?? "")
  const mainSenderAddr =
    email.from[0]?.address ??
    `${mainSenderName.toLowerCase().replace(/\s+/g, ".")}@example.com`

  const legacyEmail = useMemo(
    () => apiToLegacyEmail(email, fullMessage, threadMessages),
    [email, fullMessage, threadMessages]
  )

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

  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 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]
  )

  const savedThreadDraft = savedThreadReplyDrafts[email.id]

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

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

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

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

  const handleToggleStar = useCallback(() => {
    toggleStar.mutate({ id: email.id, flags, starred: isStarred })
  }, [email.id, flags, isStarred, toggleStar])

  const handleNotSpam = useCallback(() => {
    if (flags.includes("spam")) {
      updateFlags.mutate({
        id: email.id,
        flags: flags.filter((f) => f !== "spam"),
      })
    }
    if (email.labels.includes("spam")) {
      updateLabels.mutate({
        id: email.id,
        labels: email.labels.filter((l) => l !== "spam"),
      })
    }
  }, [email.id, flags, email.labels, updateFlags, updateLabels])

  const handlePrint = useCallback(() => {
    openConversationPrint(legacyEmail)
  }, [legacyEmail])

  return (
    <TooltipProvider delayDuration={400}>
      <div className="flex min-h-0 min-w-0 flex-1 flex-col">
        <div ref={previewScrollRef} className={MAIL_PREVIEW_SCROLL_CLASS}>
          <div
            className="h-[52px] shrink-0 bg-mail-surface sm:hidden"
            aria-hidden
          />
          <EmailViewSubjectHeader
            email={email}
            isSpamMessage={isSpam}
            onNotSpam={isSpam ? handleNotSpam : undefined}
            onPrint={handlePrint}
            onNavigateToLabel={onNavigateToLabel}
            showLabelChip={showLabelChip}
            labelBgByText={labelBgByText}
            emailLabelToSidebarFolderId={emailLabelToSidebarFolderId}
            getNavItemPrefs={getNavItemPrefs}
            folderTree={folderTree}
            labelRows={labelRows}
            currentFolderId={currentFolderId}
          />

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

          {isSpam && <SpamWhyBanner onNotSpam={handleNotSpam} />}

          {showRepliesCta ? (
            <div className="border-b border-border px-6 py-3 max-sm:px-4">
              <button
                type="button"
                onClick={() => setShowFullThread(true)}
                className="text-sm font-medium text-primary hover:underline"
              >
                {priorCount === 1
                  ? "Afficher la réponse"
                  : `Afficher les ${priorCount} réponses`}
              </button>
            </div>
          ) : null}

          {hasConversation &&
            conversation.map((msg) => {
              const isExpanded = expandedIds.has(msg.id)

              if (isExpanded) {
                return (
                  <div key={msg.id} className="border-b border-border">
                    <ExpandedMessage
                      sender={msg.from[0]?.name ?? ""}
                      senderEmail={msg.from[0]?.address ?? ""}
                      dateIso={msg.date}
                      body={msg.body_html ?? msg.body_text ?? ""}
                      isSpam={false}
                      isLast={false}
                      starred={msg.flags.includes("starred")}
                      onCollapse={() => toggleExpanded(msg.id)}
                      onPrintConversation={handlePrint}
                    />
                  </div>
                )
              }

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

          <ExpandedMessage
            sender={mainSenderName}
            senderEmail={mainSenderAddr}
            dateIso={email.date}
            body={body}
            isSpam={isSpam}
            isLast={true}
            starred={isStarred}
            attachments={mainMessageAttachments}
            onToggleStar={handleToggleStar}
            onPrintConversation={handlePrint}
          />

          {showReplyForwardBar ? (
            <div
              className={cn(
                "z-10 mt-4 hidden flex-wrap items-center gap-x-3 gap-y-2 px-4 pb-6 pl-[68px] sm:flex",
                "max-sm:static sm:sticky sm:bottom-0",
                MAIL_REPLY_BAR_CLASS
              )}
            >
              <button
                type="button"
                onClick={() => startThreadCompose("reply")}
                className={MAIL_REPLY_BUTTON_CLASS}
              >
                <Reply
                  className="h-[18px] w-[18px] shrink-0 text-muted-foreground"
                  strokeWidth={1.5}
                />
                Répondre
              </button>
              <button
                type="button"
                onClick={() => startThreadCompose("replyAll")}
                className={MAIL_REPLY_BUTTON_CLASS}
              >
                <ReplyAll
                  className="h-[18px] w-[18px] shrink-0 text-muted-foreground"
                  strokeWidth={1.5}
                />
                Répondre à tous
              </button>
              <button
                type="button"
                onClick={() => startThreadCompose("forward")}
                className={MAIL_REPLY_BUTTON_CLASS}
              >
                <Forward
                  className="h-[18px] w-[18px] shrink-0 text-muted-foreground"
                  strokeWidth={1.5}
                />
                Transférer
              </button>
            </div>
          ) : null}

          {inlineCompose ? (
            <div
              ref={threadComposeAnchorRef}
              className="mt-6 px-4 pb-6 pl-[68px] max-sm:pl-4"
            >
              <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={legacyEmail}
                  />
                </div>
              </div>
            </div>
          ) : null}
        </div>
      </div>
    </TooltipProvider>
  )
}
