"use client"

import { useEffect, useMemo, useRef, useCallback, useState, useDeferredValue } from "react"
import { Loader2, RefreshCw, X } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Progress } from "@/components/ui/progress"
import {
  useActiveDiscoveryScan,
  useAddDiscoveredContact,
  useBlockDiscoveredProfile,
  useCancelDiscoveryScan,
  useDiscoveryCounts,
  useEnrichDiscoveredProfile,
  useIgnoreDiscoveredProfile,
  extractDiscoveryGroupEmails,
  flattenOtherContactPages,
  useOtherDiscoveredContacts,
  useStartDiscoveryScan,
  scanProgressLabel,
} from "@/lib/api/hooks/use-contact-discovery"
import { fullContactToApiContact } from "@/lib/api/adapters"
import { useContactsList } from "@/lib/contacts/use-contacts-list"
import {
  isSuggestableDiscoveryGroup,
} from "@/lib/contacts/discovery-utils"
import {
  discoveryGroupReactKey,
  normalizeDiscoveryGroup,
} from "@/lib/contacts/discovery-grouping"
import type { ApiDiscoveredProfileGroup } from "@/lib/contacts/discovery-types"
import type { FullContact } from "@/lib/contacts/types"
import { useBlockedSendersStore } from "@/lib/stores/blocked-senders-store"
import {
  CONTACTS_HEADING_TEXT,
  CONTACTS_MUTED_TEXT,
  CONTACTS_PAGE_INFO_BANNER_CLASS,
  CONTACTS_PAGE_INFO_BANNER_ICON_CLASS,
  CONTACTS_PAGE_SECTION_TITLE_CLASS,
  CONTACTS_PRIMARY_BTN_CLASS,
} from "@/lib/contacts-chrome-classes"
import {
  DiscoveryCardsMasonry,
  DiscoveryCardsMasonryItem,
  DiscoveryCardsMasonrySentinel,
} from "@/components/gmail/contacts-page/discovery-cards-masonry"
import { SuggestedContactCard } from "@/components/gmail/contacts-page/suggested-contact-card"
import { useDiscoveryScrollLoad } from "@/components/gmail/contacts-page/use-discovery-scroll-load"
import { cn } from "@/lib/utils"

interface OtherContactsViewProps {
  searchQuery: string
}

export function OtherContactsView({ searchQuery }: OtherContactsViewProps) {
  const deferredSearchQuery = useDeferredValue(searchQuery.trim())
  const { bookId } = useContactsList()
  const { data: discoveryCounts } = useDiscoveryCounts()
  const { data: activeScan } = useActiveDiscoveryScan()
  const isRunning =
    activeScan != null &&
    (activeScan.status === "running" || activeScan.status === "pending")

  const {
    data,
    isLoading,
    refetch,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useOtherDiscoveredContacts(!isRunning, deferredSearchQuery)
  const groups = useMemo(() => flattenOtherContactPages(data), [data])
  const loadMoreRef = useRef<HTMLDivElement>(null)
  const startScan = useStartDiscoveryScan()
  const cancelScan = useCancelDiscoveryScan()
  const addDiscoveredContact = useAddDiscoveredContact()
  const ignoreProfile = useIgnoreDiscoveredProfile()
  const blockProfile = useBlockDiscoveredProfile()
  const enrichProfile = useEnrichDiscoveredProfile()
  const blockSenders = useBlockedSendersStore((s) => s.blockSenders)
  const completedHandled = useRef(false)
  const [dismissedKeys, setDismissedKeys] = useState<Set<string>>(() => new Set())

  const dismissCard = useCallback((cardKey: string) => {
    setDismissedKeys((prev) => {
      if (prev.has(cardKey)) return prev
      const next = new Set(prev)
      next.add(cardKey)
      return next
    })
  }, [])

  const restoreCard = useCallback((cardKey: string) => {
    setDismissedKeys((prev) => {
      if (!prev.has(cardKey)) return prev
      const next = new Set(prev)
      next.delete(cardKey)
      return next
    })
  }, [])

  useEffect(() => {
    if (completedHandled.current && !isRunning) return
    if (!isRunning && activeScan == null) {
      completedHandled.current = true
      void refetch()
    }
  }, [isRunning, activeScan, refetch])

  useEffect(() => {
    if (isRunning) completedHandled.current = false
  }, [isRunning])

  const filtered = useMemo(() => {
    return groups
      .map((g) => normalizeDiscoveryGroup(g))
      .filter((g): g is ApiDiscoveredProfileGroup => g != null)
      .filter(isSuggestableDiscoveryGroup)
      .filter((g) => !dismissedKeys.has(discoveryGroupReactKey(g)))
  }, [groups, dismissedKeys])

  const isSearchPending = searchQuery.trim() !== deferredSearchQuery
  const serverSuggestionCount =
    deferredSearchQuery
      ? (data?.pages[0]?.total ?? filtered.length)
      : (discoveryCounts?.other_contacts ?? data?.pages[0]?.total ?? filtered.length)

  const suggestionCountLabel = deferredSearchQuery
    ? String(filtered.length)
    : hasNextPage
      ? `${filtered.length} / ${serverSuggestionCount}`
      : String(filtered.length)

  const loadMore = useCallback(() => {
    if (!hasNextPage || isFetchingNextPage) return
    void fetchNextPage()
  }, [hasNextPage, isFetchingNextPage, fetchNextPage])

  useDiscoveryScrollLoad({
    sentinelRef: loadMoreRef,
    hasNextPage: Boolean(hasNextPage),
    isFetchingNextPage,
    onLoadMore: loadMore,
    maxAutoLoads: 1,
  })

  function handleScan() {
    if (isRunning) return
    startScan.mutate(bookId)
  }

  function handleAdd(group: ApiDiscoveredProfileGroup, buildContact: () => FullContact) {
    const profileId = group.profile?.id ?? group.profile_ids[0]
    if (!profileId || !bookId) return
    const cardKey = discoveryGroupReactKey(group)
    dismissCard(cardKey)
    addDiscoveredContact.mutate(
      {
        bookId,
        profileId,
        contact: fullContactToApiContact(buildContact()),
      },
      { onError: () => restoreCard(cardKey) },
    )
  }

  function handleIgnore(group: ApiDiscoveredProfileGroup, profileId: string) {
    const cardKey = discoveryGroupReactKey(group)
    dismissCard(cardKey)
    ignoreProfile.mutate(profileId, { onError: () => restoreCard(cardKey) })
  }

  function handleBlock(group: ApiDiscoveredProfileGroup, profileId: string) {
    const cardKey = discoveryGroupReactKey(group)
    const emails = extractDiscoveryGroupEmails(group)
    if (emails.length) blockSenders(emails)
    dismissCard(cardKey)
    blockProfile.mutate(profileId, {
      onSuccess: (res) => {
        if (res.emails?.length) blockSenders(res.emails)
      },
      onError: () => restoreCard(cardKey),
    })
  }

  const enrichingProfileId =
    enrichProfile.isPending && typeof enrichProfile.variables === "string"
      ? enrichProfile.variables
      : null

  const progress = activeScan?.progress_percent ?? 0
  const scanLabel = activeScan ? scanProgressLabel(activeScan) : null

  return (
    <div className="px-6 py-6 text-foreground">
      <div className={cn(CONTACTS_PAGE_INFO_BANNER_CLASS, "flex flex-col gap-4")}>
        <div className="flex w-full items-center gap-4">
          <div className={CONTACTS_PAGE_INFO_BANNER_ICON_CLASS}>
            <span className="text-2xl">📬</span>
          </div>
          <h2 className={cn("min-w-0 flex-1 text-base font-medium", CONTACTS_HEADING_TEXT)}>
            Contacts détectés dans vos e-mails
          </h2>
          <div className="flex shrink-0 flex-col items-stretch gap-2">
            <Button
              onClick={handleScan}
              disabled={isRunning || startScan.isPending}
              className={CONTACTS_PRIMARY_BTN_CLASS}
            >
              {isRunning || startScan.isPending ? (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              ) : (
                <RefreshCw className="mr-2 h-4 w-4" />
              )}
              {isRunning ? (
                "Analyse en cours…"
              ) : (
                <>
                  <span className="sm:hidden">Analyser</span>
                  <span className="hidden sm:inline">Analyser toutes les boîtes</span>
                </>
              )}
            </Button>
            {isRunning && (
              <Button
                variant="outline"
                size="sm"
                onClick={() => cancelScan.mutate()}
                disabled={cancelScan.isPending}
              >
                {cancelScan.isPending ? (
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <X className="mr-2 h-4 w-4" />
                )}
                Annuler
              </Button>
            )}
          </div>
        </div>
        <p className={cn("w-full text-sm", CONTACTS_MUTED_TEXT)}>
          Analyse complète de toutes vos boîtes mail. Les listes de diffusion, e-mails jetables et expéditeurs spam sont exclus.
        </p>
        {activeScan?.status === "failed" && activeScan.error_message && (
          <p className="w-full text-xs text-destructive">{activeScan.error_message}</p>
        )}
        {isRunning && scanLabel && activeScan && (
          <div className="w-full space-y-2">
            <p className={cn("text-xs", CONTACTS_MUTED_TEXT)}>{scanLabel}</p>
            <Progress value={Math.min(100, progress)} className="h-2 w-full" />
          </div>
        )}
      </div>

      <div className="mb-4 flex items-center justify-between">
        <h3 className={CONTACTS_PAGE_SECTION_TITLE_CLASS}>
          Suggestions ({suggestionCountLabel})
        </h3>
      </div>

      {isLoading && !isRunning && (
        <p className={cn("py-8 text-center text-sm", CONTACTS_MUTED_TEXT)}>
          {isSearchPending ? "Recherche…" : "Chargement…"}
        </p>
      )}

      {!isLoading && filtered.length === 0 && !isRunning && (
        <p className={cn("py-8 text-center text-sm", CONTACTS_MUTED_TEXT)}>
          {deferredSearchQuery
            ? "Aucun contact ne correspond à votre recherche."
            : "Aucun contact détecté. Lancez une analyse pour scanner tous vos messages."}
        </p>
      )}

      <DiscoveryCardsMasonry
        footer={
          (hasNextPage || isFetchingNextPage) ? (
            <DiscoveryCardsMasonrySentinel sentinelRef={loadMoreRef}>
              {isFetchingNextPage ? (
                <>
                  <Loader2 className="h-5 w-5 animate-spin text-muted-foreground" />
                  <p className={cn("text-xs", CONTACTS_MUTED_TEXT)}>Chargement…</p>
                </>
              ) : (
                <p className={cn("text-xs", CONTACTS_MUTED_TEXT)}>
                  {deferredSearchQuery
                    ? `${filtered.length} sur ${serverSuggestionCount} résultats`
                    : `${filtered.length} sur ${serverSuggestionCount} affichés`}
                </p>
              )}
            </DiscoveryCardsMasonrySentinel>
          ) : null
        }
      >
        {filtered.map((group) => {
          const profileId = group.profile?.id ?? group.profile_ids[0]
          if (!profileId) return null
          const reactKey = discoveryGroupReactKey(group)
          return (
            <DiscoveryCardsMasonryItem key={reactKey}>
              <SuggestedContactCard
                group={group}
                mode="suggest"
                busy={profileId === enrichingProfileId}
                onAdd={(buildContact) => handleAdd(group, buildContact)}
                onEnrich={() => enrichProfile.mutate(profileId)}
                onIgnore={() => handleIgnore(group, profileId)}
                onBlock={() => handleBlock(group, profileId)}
              />
            </DiscoveryCardsMasonryItem>
          )
        })}
      </DiscoveryCardsMasonry>
    </div>
  )
}
