import type { QueryClient } from '@tanstack/react-query'
import type { ApiContact } from '@/lib/api/types'
import { contactApiPath } from '@/lib/contacts/contact-api-path'
import type { FullContact } from '@/lib/contacts/types'

function contactMatchesPath(api: ApiContact, apiPath: string): boolean {
  const normalizedPath = apiPath.replace(/^\/+/, '')
  const contactPath = api.path?.replace(/^\/+/, '')
  return (
    contactPath === normalizedPath ||
    api.uid === normalizedPath ||
    contactPath?.endsWith(`/${normalizedPath}`) === true ||
    contactPath?.endsWith(`/${normalizedPath}.vcf`) === true
  )
}

/** Merge selection snapshot with latest React Query cache (etag, path). */
export function resolveContactForUpdate(
  queryClient: QueryClient,
  contact: FullContact,
): FullContact {
  const api = findApiContactInCaches(queryClient, contact)
  if (!api) return contact
  const etag = contact.etag ?? api.etag
  const path = contact.path ?? api.path
  if (etag === contact.etag && path === contact.path) return contact
  return { ...contact, etag, path }
}

export function findApiContactInCaches(
  queryClient: QueryClient,
  contact: Pick<FullContact, 'id' | 'path'>,
): ApiContact | undefined {
  const apiPath = contactApiPath(contact)
  for (const [, list] of queryClient.getQueriesData<ApiContact[]>({
    queryKey: ['contacts'],
  })) {
    if (!list) continue
    const hit = list.find(
      (c) => c.uid === contact.id || contactMatchesPath(c, apiPath),
    )
    if (hit) return hit
  }
  return undefined
}

export function appendContactToBookCache(
  queryClient: QueryClient,
  bookId: string,
  contact: ApiContact,
) {
  if (!contact.uid && !contact.path) return
  queryClient.setQueryData<ApiContact[]>(['contacts', bookId], (old) => {
    const list = old ?? []
    const uid = contact.uid
    if (uid && list.some((item) => item.uid === uid)) return list
    return [...list, contact]
  })
}

export function replaceContactInBookCaches(
  queryClient: QueryClient,
  apiPath: string,
  patch: Partial<ApiContact>,
) {
  for (const [key, list] of queryClient.getQueriesData<ApiContact[]>({
    queryKey: ['contacts'],
  })) {
    if (!list) continue
    let changed = false
    const next = list.map((item) => {
      if (!contactMatchesPath(item, apiPath)) return item
      changed = true
      return { ...item, ...patch }
    })
    if (changed) {
      queryClient.setQueryData(key, next)
    }
  }
}
