"use client"

import { useMemo } from "react"
import { useLabels } from "@/lib/api/hooks/use-folder-label-queries"
import { useUnifiedFolders } from "@/lib/api/hooks/use-unified-folder-queries"
import { useImapFolders } from "@/lib/api/hooks/use-imap-folders"
import { useMailAccounts } from "@/lib/api/hooks/use-mail-queries"
import { useContactsList } from "@/lib/contacts/use-contacts-list"
import { fullContactDisplayName } from "@/lib/contacts/types"
import type { AgendaInvitationExclusion } from "@/lib/agenda/agenda-settings-types"
import { exclusionKey } from "@/lib/agenda/agenda-settings-types"
import {
  buildDestinationMailboxes,
  destinationEmailFromStoredKey,
} from "@/lib/agenda/agenda-destination-identities"
import { identityKey } from "@/lib/agenda/agenda-store"
import { useComposeIdentitiesStore } from "@/lib/stores/compose-identities-store"

export type AgendaImportSuggestion = AgendaInvitationExclusion & {
  id: string
  group: string
}

const MAILBOX_SUGGESTIONS: AgendaInvitationExclusion[] = [
  { type: "mailbox", value: "spam", label: "Spam" },
  { type: "mailbox", value: "trash", label: "Corbeille" },
  { type: "mailbox", value: "promotions", label: "Promotions" },
  { type: "mailbox", value: "social", label: "Réseaux sociaux" },
  { type: "mailbox", value: "updates", label: "Notifications" },
]

function matchesQuery(text: string, query: string): boolean {
  return text.toLowerCase().includes(query.toLowerCase())
}

export function useAgendaDestinationMailboxes() {
  const identities = useComposeIdentitiesStore((s) => s.identities)
  const { data: accounts = [] } = useMailAccounts()
  return useMemo(
    () => buildDestinationMailboxes(identities, accounts.map((a) => a.email)),
    [identities, accounts],
  )
}

export function useAgendaInvitationSuggestions(
  query: string,
  taken: Set<string>,
  opts?: { types?: AgendaInvitationExclusion["type"][] },
) {
  const { contacts } = useContactsList()
  const identities = useComposeIdentitiesStore((s) => s.identities)
  const { data: accounts = [] } = useMailAccounts()
  const destinationMailboxes = useMemo(
    () => buildDestinationMailboxes(identities, accounts.map((a) => a.email)),
    [identities, accounts],
  )
  const { data: labels = [] } = useLabels()
  const { data: unifiedFolders = [] } = useUnifiedFolders("all")
  const { folders: imapFolders = [] } = useImapFolders()

  return useMemo(() => {
    const q = query.trim()
    const allowed = opts?.types
    const includeType = (type: AgendaInvitationExclusion["type"]) =>
      !allowed || allowed.includes(type)

    const out: AgendaImportSuggestion[] = []

    const seenSuggestionIds = new Set<string>()
    const push = (suggestion: AgendaImportSuggestion) => {
      if (seenSuggestionIds.has(suggestion.id)) return
      seenSuggestionIds.add(suggestion.id)
      out.push(suggestion)
    }

    if (includeType("not_in_contacts")) {
      const allRule: AgendaInvitationExclusion = {
        type: "not_in_contacts",
        value: "",
        label: "Toute personne pas dans les contacts",
      }
      const allId = exclusionKey(allRule)
      if (!taken.has(allId) && (!q || matchesQuery(allRule.label, q))) {
        push({ ...allRule, id: allId, group: "Règles contacts" })
      }
      const seenIdentityKeys = new Set<string>()
      for (const identity of identities) {
        const key = identityKey(identity.email, identity.accountId)
        if (seenIdentityKeys.has(key)) continue
        seenIdentityKeys.add(key)
        const rule: AgendaInvitationExclusion = {
          type: "not_in_contacts",
          value: key,
          label: `Personnes pas dans les contacts de ${identity.name || identity.email}`,
        }
        const id = exclusionKey(rule)
        if (taken.has(id)) continue
        if (q && !matchesQuery(rule.label, q) && !matchesQuery(identity.email, q)) continue
        push({ ...rule, id, group: "Règles contacts" })
      }
    }

    if (includeType("identity")) {
      for (const mailbox of destinationMailboxes) {
        const rule: AgendaInvitationExclusion = {
          type: "identity",
          value: mailbox.key,
          label: mailbox.label,
        }
        const id = exclusionKey(rule)
        if (taken.has(id)) continue
        if (q && !matchesQuery(mailbox.label, q) && !matchesQuery(mailbox.key, q)) continue
        push({ ...rule, id, group: "Mails de destination" })
      }
    }

    if (includeType("contact")) {
      for (const contact of contacts) {
        const name = fullContactDisplayName(contact)
        for (const { value: email } of contact.emails) {
          if (!email) continue
          const rule: AgendaInvitationExclusion = {
            type: "contact",
            value: email,
            label: name ? `${name} <${email}>` : email,
          }
          const id = exclusionKey(rule)
          if (taken.has(id)) continue
          if (q && !matchesQuery(rule.label, q) && !matchesQuery(email, q)) continue
          push({ ...rule, id, group: "Contacts" })
          if (out.length > 40) break
        }
      }
    }

    if (includeType("email") && q.includes("@")) {
      const rule: AgendaInvitationExclusion = {
        type: "email",
        value: q,
        label: q,
      }
      const id = exclusionKey(rule)
      if (!taken.has(id)) push({ ...rule, id, group: "Adresses" })
    }

    if (includeType("label")) {
      for (const label of labels) {
        const rule: AgendaInvitationExclusion = {
          type: "label",
          value: label.name,
          label: `Libellé · ${label.name}`,
        }
        const id = exclusionKey(rule)
        if (taken.has(id)) continue
        if (q && !matchesQuery(label.name, q)) continue
        push({ ...rule, id, group: "Libellés" })
      }
    }

    if (includeType("folder")) {
      const folders = [
        ...unifiedFolders.map((f) => ({
          value: f.id,
          label: `Dossier · ${f.name}`,
        })),
        ...imapFolders.map((f) => ({
          value: f.name,
          label: `Dossier · ${f.name}`,
        })),
      ]
      for (const folder of folders) {
        const rule: AgendaInvitationExclusion = {
          type: "folder",
          value: folder.value,
          label: folder.label,
        }
        const id = exclusionKey(rule)
        if (taken.has(id)) continue
        if (q && !matchesQuery(folder.label, q)) continue
        push({ ...rule, id, group: "Dossiers" })
      }
    }

    if (includeType("mailbox")) {
      for (const mailbox of MAILBOX_SUGGESTIONS) {
        const id = exclusionKey(mailbox)
        if (taken.has(id)) continue
        if (q && !matchesQuery(mailbox.label, q)) continue
        push({ ...mailbox, id, group: "Boîtes mail" })
      }
    }

    return out.slice(0, 12)
  }, [
    contacts,
    identities,
    destinationMailboxes,
    labels,
    unifiedFolders,
    imapFolders,
    query,
    taken,
    opts?.types,
  ])
}

export function identityLabelFromKey(key: string): string {
  const identities = useComposeIdentitiesStore.getState().identities
  const found = identities.find((i) => identityKey(i.email, i.accountId) === key)
  if (!found) return key
  return `${found.name} <${found.email}>`
}

export function useAgendaSettingsIdentityOptions() {
  const identities = useComposeIdentitiesStore((s) => s.identities)
  return useMemo(() => {
    const seen = new Set<string>()
    const out: { key: string; label: string }[] = []
    for (const identity of identities) {
      const key = identityKey(identity.email, identity.accountId)
      if (seen.has(key)) continue
      seen.add(key)
      out.push({
        key,
        label: `${identity.name} <${identity.email}>`,
      })
    }
    return out
  }, [identities])
}

export function useAgendaSettingsDestinationOptions() {
  return useAgendaDestinationMailboxes()
}

/** Libellé d'une clé stockée (legacy identité ou email de destination). */
export function destinationLabelFromStoredKey(
  key: string,
  mailboxes: ReturnType<typeof buildDestinationMailboxes>,
): string {
  return (
    mailboxes.find((m) => m.key === destinationEmailFromStoredKey(key))?.label ??
    destinationEmailFromStoredKey(key)
  )
}
