"use client"

import { useMemo, type MouseEvent } from "react"
import { cn } from "@/lib/utils"
import {
  labelPillTextClassForBgHex,
  labelPillTextClassForTailwindBgUtility,
} from "@/lib/label-pill-contrast"
import type { FolderTreeNode, LabelRowItem } from "@/lib/sidebar-nav-data"

/** Libellés système masqués en pastilles liste (Gmail : pastilles = libellés perso / dossiers). */
export const MAIL_LABEL_STRIP_EXCLUDE = new Set([
  "inbox",
  "sent",
  "drafts",
  "spam",
  "starred",
  "snoozed",
  "trash",
  "important",
  "scheduled",
])

export function buildLabelTextToNavColorClass(
  tree: FolderTreeNode[],
  labelRows: LabelRowItem[]
): Map<string, string> {
  const m = new Map<string, string>()
  const put = (text: string, color: string | undefined) => {
    if (!color) return
    m.set(text.toLowerCase(), color)
  }
  const walk = (nodes: FolderTreeNode[]) => {
    for (const n of nodes) {
      put(n.label, n.color)
      if (n.children?.length) walk(n.children)
    }
  }
  walk(tree)
  for (const r of labelRows) put(r.label, r.color)
  return m
}

export function mailLabelShouldShowInListStrip(
  lab: string,
  emailLabelToSidebarFolderId: Record<string, string>,
  getNavItemPrefs: (id: string) => { messages: string },
  labelRows?: readonly LabelRowItem[]
): boolean {
  if (MAIL_LABEL_STRIP_EXCLUDE.has(lab.toLowerCase())) return false
  const fid = emailLabelToSidebarFolderId[lab]
  let row: LabelRowItem | undefined
  if (fid) row = labelRows?.find((r) => r.id === fid)
  if (!row && labelRows?.length) {
    row = labelRows.find((r) => r.label.toLowerCase() === lab.toLowerCase())
  }
  if (row) {
    if (row.enabled === false) return false
    if (row.showInMessageList === false) return false
  }
  if (fid) return getNavItemPrefs(fid).messages !== "hide"
  return true
}

function findNodeLabel(tree: FolderTreeNode[], folderId: string): string | null {
  for (const n of tree) {
    if (n.id === folderId) return n.label
    if (n.children?.length) {
      const hit = findNodeLabel(n.children, folderId)
      if (hit) return hit
    }
  }
  return null
}

function collectFolderLabelsSet(tree: FolderTreeNode[]): Set<string> {
  const s = new Set<string>()
  const walk = (nodes: FolderTreeNode[]) => {
    for (const n of nodes) {
      s.add(n.label.toLowerCase())
      if (n.children?.length) walk(n.children)
    }
  }
  walk(tree)
  return s
}

const PILL_BASE =
  "shrink-0 whitespace-nowrap rounded font-semibold leading-snug opacity-[0.96] transition-[filter,opacity] duration-150 hover:opacity-100 hover:brightness-[0.98]"

function MailLabelPill({
  label,
  displayText,
  bgClass,
  size,
  onClick,
  onRemoveClick,
}: {
  label: string
  displayText: string
  bgClass: string | undefined
  size: "list" | "header"
  onClick: (e: MouseEvent) => void
  onRemoveClick?: (e: MouseEvent) => void
}) {
  const sizeClass =
    size === "list"
      ? "px-1 py-px text-[11px]"
      : "inline-flex items-center gap-0.5 px-1.5 py-0.5 text-xs"

  return (
    <button
      type="button"
      title={label}
      className={cn(
        PILL_BASE,
        sizeClass,
        bgClass
          ? cn(bgClass, labelPillTextClassForTailwindBgUtility(bgClass))
          : cn(
              "border border-transparent bg-[#e8eaed] hover:bg-[#dadce0]",
              labelPillTextClassForBgHex("#e8eaed")
            )
      )}
      onClick={onClick}
    >
      {displayText}
      {onRemoveClick ? (
        <span
          role="button"
          tabIndex={0}
          className={cn(
            "text-inherit opacity-70 hover:opacity-100",
            size === "header" ? "ml-0.5" : "ml-0.5"
          )}
          aria-label={`Retirer le libellé ${displayText}`}
          onClick={onRemoveClick}
          onKeyDown={(e) => {
            if (e.key === "Enter") onRemoveClick(e as unknown as MouseEvent)
          }}
        >
          ×
        </span>
      ) : null}
    </button>
  )
}

type MailLabelPillStripProps = {
  labels: string[] | undefined
  labelBgByText: Map<string, string>
  emailLabelToSidebarFolderId: Record<string, string>
  getNavItemPrefs: (id: string) => { messages: string }
  onLabelNavigate: (label: string) => void
  variant: "list" | "header"
  /** En-tête message : filtre additionnel (ex. libellés système avec libellé lisible). */
  showLabel?: (label: string) => boolean
  /** En-tête : nom affiché (Boîte de réception, etc.). */
  resolveDisplayName?: (label: string) => string
  /** En-tête : pastille spam avec action. */
  spamChip?: { onNotSpam: () => void }
  /** En-tête : bouton × sur chaque pastille. */
  showRemoveOnPills?: boolean
  /** Dossier actuel (id) — son label est masqué en list, mais pas ses sous-dossiers. */
  currentFolderId?: string
  /** Libellés navigation (couleurs / enabled / showInMessageList). */
  labelRows?: readonly LabelRowItem[]
  /** Arbre dossiers (tri pastilles liste, masquage libellé du dossier courant). */
  folderTree?: FolderTreeNode[]
}

export function MailLabelPillStrip({
  labels,
  labelBgByText,
  emailLabelToSidebarFolderId,
  getNavItemPrefs,
  onLabelNavigate,
  variant,
  showLabel,
  resolveDisplayName,
  spamChip,
  showRemoveOnPills,
  currentFolderId,
  folderTree,
  labelRows,
}: MailLabelPillStripProps) {
  const currentFolderLabel = useMemo(() => {
    if (!currentFolderId || !folderTree) return null
    return findNodeLabel(folderTree, currentFolderId)
  }, [currentFolderId, folderTree])

  const folderLabelsLower = useMemo(() => {
    if (!folderTree) return new Set<string>()
    return collectFolderLabelsSet(folderTree)
  }, [folderTree])

  const shown = useMemo(() => {
    const filtered = (labels ?? []).filter((lab) => {
      if (variant === "list") {
        if (
          !mailLabelShouldShowInListStrip(
            lab,
            emailLabelToSidebarFolderId,
            getNavItemPrefs,
            labelRows
          )
        ) {
          return false
        }
        if (currentFolderLabel && lab.toLowerCase() === currentFolderLabel.toLowerCase()) {
          return false
        }
        return true
      }
      if (!mailLabelShouldShowInListStrip(lab, emailLabelToSidebarFolderId, getNavItemPrefs, labelRows)) {
        return false
      }
      if (lab === "spam" && spamChip) return false
      if (showLabel && !showLabel(lab)) return false
      return true
    })

    if (variant === "list" && folderTree) {
      filtered.sort((a, b) => {
        const aIsFolder = folderLabelsLower.has(a.toLowerCase())
        const bIsFolder = folderLabelsLower.has(b.toLowerCase())
        if (aIsFolder && !bIsFolder) return -1
        if (!aIsFolder && bIsFolder) return 1
        return 0
      })
    }

    return filtered
  }, [labels, variant, emailLabelToSidebarFolderId, getNavItemPrefs, labelRows, currentFolderLabel, folderTree, folderLabelsLower, spamChip, showLabel])

  const hasSpam = variant === "header" && spamChip
  if (shown.length === 0 && !hasSpam) return null

  const wrapClass =
    variant === "list"
      ? "flex shrink-0 items-center gap-1"
      : "contents"

  return (
    <span className={wrapClass}>
      {hasSpam ? (
        <button
          type="button"
          onClick={() => spamChip!.onNotSpam()}
          className={cn(
            PILL_BASE,
            "inline-flex items-center gap-0.5 border border-transparent bg-[#e8eaed] px-1.5 py-0.5 text-xs hover:bg-[#dadce0]",
            labelPillTextClassForBgHex("#e8eaed")
          )}
          title="Signaler comme non-spam et retirer ce libellé"
        >
          Spam
          <span className="opacity-70 hover:opacity-100" aria-hidden>
            ×
          </span>
        </button>
      ) : null}
      {shown.map((lab) => {
        const bg = labelBgByText.get(lab.toLowerCase())
        const displayText = resolveDisplayName?.(lab) ?? lab
        return (
          <MailLabelPill
            key={lab}
            label={lab}
            displayText={displayText}
            bgClass={bg}
            size={variant === "list" ? "list" : "header"}
            onClick={(e) => {
              e.stopPropagation()
              onLabelNavigate(lab)
            }}
            onRemoveClick={
              showRemoveOnPills
                ? (e) => {
                    e.stopPropagation()
                  }
                : undefined
            }
          />
        )
      })}
    </span>
  )
}
