"use client"

import { useCallback, useMemo } from "react"
import type { CatalogLabelPresence } from "@/components/gmail/email-label-picker-block"
import { resolveLabelPickerVisual } from "@/lib/label-picker-visual"
import type { FolderTreeNode } from "@/lib/sidebar-nav-data"
import {
  LABEL_PICKER_EXCLUDE,
} from "@/lib/mail-list/label-actions"
import {
  collectTreeLabels,
} from "@/components/gmail/email-list/email-list-helpers"
import type { EmailListData } from "@/components/gmail/email-list/hooks/use-email-list-data"

export function useEmailListLabels(data: EmailListData) {
  const {
    allEmails,
    sidebarNav,
    setLabelEdits,
    mailActions,
  } = data

  const collectAllFolderLabels = useCallback((): 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(sidebarNav.folderTree)
    return s
  }, [sidebarNav.folderTree])

  const moveEmailsToTarget = useCallback(
    (emailIds: string[], targetId: string) => {
      if (emailIds.length === 0) return
      const folderLabel = sidebarNav.folderIdToLabel[targetId]
      const isSystemTarget = ["inbox", "sent", "drafts", "spam", "trash"].includes(targetId)
      const allFolderLabels = collectAllFolderLabels()

      setLabelEdits((prev) => {
        const nextAdd = { ...prev.additions }
        const nextRem = { ...prev.removals }

        for (const id of emailIds) {
          const email = allEmails.find((e) => e.id === id)
          const currentLabels = email?.labels ?? []

          if (isSystemTarget) {
            if (targetId === "inbox") {
              for (const lab of currentLabels) {
                if (allFolderLabels.has(lab.toLowerCase())) {
                  const cur = nextRem[id] ?? []
                  if (!cur.some((l: string) => l.toLowerCase() === lab.toLowerCase())) {
                    nextRem[id] = [...cur, lab]
                  }
                }
              }
            }
          } else if (folderLabel) {
            for (const lab of currentLabels) {
              if (allFolderLabels.has(lab.toLowerCase()) && lab.toLowerCase() !== folderLabel.toLowerCase()) {
                const cur = nextRem[id] ?? []
                if (!cur.some((l: string) => l.toLowerCase() === lab.toLowerCase())) {
                  nextRem[id] = [...cur, lab]
                }
              }
            }
            if (!currentLabels.some((l) => l.toLowerCase() === folderLabel.toLowerCase())) {
              nextAdd[id] = [...(nextAdd[id] ?? []), folderLabel]
            }
            const inboxIdx = currentLabels.findIndex((l) => l.toLowerCase() === "inbox")
            if (inboxIdx >= 0 || !email?.labels?.length || email.labels.includes("inbox")) {
              const cur = nextRem[id] ?? []
              if (!cur.some((l) => l.toLowerCase() === "inbox")) {
                nextRem[id] = [...cur, "inbox"]
              }
            }
          }
        }
        return { additions: nextAdd, removals: nextRem }
      })

      if (!isSystemTarget || targetId === "inbox") {
        mailActions.pushRecentMoveTarget(targetId)
      }

      if (isSystemTarget && targetId !== "inbox") {
        mailActions.hideEmails(emailIds)
        mailActions.pushRecentMoveTarget(targetId)
      }
    },
    [allEmails, sidebarNav.folderIdToLabel, collectAllFolderLabels, setLabelEdits, mailActions]
  )

  const catalogLabels = useMemo(() => {
    const s = new Set<string>()
    for (const l of collectTreeLabels(sidebarNav.folderTree)) s.add(l)
    for (const row of sidebarNav.labelRows) s.add(row.label)
    for (const e of allEmails) {
      for (const lab of e.labels ?? []) {
        if (!LABEL_PICKER_EXCLUDE.has(lab)) s.add(lab)
      }
    }
    return [...s].sort((a, b) => a.localeCompare(b, "fr"))
  }, [sidebarNav.folderTree, sidebarNav.labelRows, allEmails])

  const resolveLabelVisual = useCallback(
    (label: string) =>
      resolveLabelPickerVisual(label, {
        folderTree: sidebarNav.folderTree,
        labelRows: sidebarNav.labelRows,
        emailLabelToSidebarFolderId: sidebarNav.emailLabelToSidebarFolderId,
      }),
    [
      sidebarNav.folderTree,
      sidebarNav.labelRows,
      sidebarNav.emailLabelToSidebarFolderId,
    ]
  )

  const resolveLabelCasing = useCallback(
    (raw: string) => {
      const t = raw.trim()
      if (!t) return ""
      const hit = catalogLabels.find((c) => c.toLowerCase() === t.toLowerCase())
      return hit ?? t
    },
    [catalogLabels]
  )

  const addLabelToEmails = useCallback(
    (ids: string[], label: string) => {
      const resolved = resolveLabelCasing(label)
      if (!resolved || ids.length === 0) return
      sidebarNav.ensureLabelRowForLabelText(resolved)
      setLabelEdits((prev) => {
        const nextAdd = { ...prev.additions }
        const nextRem = { ...prev.removals }
        for (const id of ids) {
          const base = allEmails.find((e) => e.id === id)
          const currentLabels = base?.labels ?? []
          if (currentLabels.some((x: string) => x.toLowerCase() === resolved.toLowerCase())) {
            continue
          }
          nextAdd[id] = [...(nextAdd[id] ?? []), resolved]
        }
        return { additions: nextAdd, removals: nextRem }
      })
    },
    [resolveLabelCasing, allEmails, sidebarNav, setLabelEdits]
  )

  const getCatalogLabelPresence = useCallback(
    (ids: string[], catalogLabel: string): CatalogLabelPresence => {
      const resolved = resolveLabelCasing(catalogLabel)
      if (!resolved || ids.length === 0) return "none"
      const lc = resolved.toLowerCase()
      let n = 0
      for (const id of ids) {
        const e = allEmails.find((x) => x.id === id)
        const labels = e?.labels ?? []
        if (labels.some((l: string) => l.toLowerCase() === lc)) n++
      }
      if (n === 0) return "none"
      if (n === ids.length) return "all"
      return "some"
    },
    [allEmails, resolveLabelCasing]
  )

  const toggleLabelOnEmails = useCallback(
    (ids: string[], label: string) => {
      const resolved = resolveLabelCasing(label)
      if (!resolved || ids.length === 0) return

      setLabelEdits((prev) => {
        const presence = (id: string) => {
          const e = allEmails.find((x) => x.id === id)
          if (!e) return false
          return (e.labels ?? []).some(
            (l: string) => l.toLowerCase() === resolved.toLowerCase()
          )
        }
        const allHave = ids.every((id) => presence(id))
        const nextAdd = { ...prev.additions }
        const nextRem = { ...prev.removals }

        if (allHave) {
          for (const id of ids) {
            nextRem[id] = [...(nextRem[id] ?? []), resolved]
          }
        } else {
          const anyMissing = ids.some((id) => !presence(id))
          if (anyMissing) {
            queueMicrotask(() => sidebarNav.ensureLabelRowForLabelText(resolved))
          }
          for (const id of ids) {
            if (!presence(id)) {
              nextAdd[id] = [...(nextAdd[id] ?? []), resolved]
            }
          }
        }
        return { additions: nextAdd, removals: nextRem }
      })
    },
    [allEmails, resolveLabelCasing, sidebarNav, setLabelEdits]
  )

  return {
    collectAllFolderLabels,
    moveEmailsToTarget,
    catalogLabels,
    resolveLabelVisual,
    resolveLabelCasing,
    addLabelToEmails,
    toggleLabelOnEmails,
    getCatalogLabelPresence,
  }
}

export type EmailListLabels = ReturnType<typeof useEmailListLabels>
