"use client"

import { useEffect, useRef } from "react"
import { useAuthStore } from "@/lib/api/auth-store"
import {
  useMailSettings,
  useUpdateMailSettings,
} from "@/lib/api/hooks/use-mail-settings"
import {
  apiSettingsToStore,
  storeSettingsToPatch,
} from "@/lib/mail-settings/map-api-settings"
import { useMailSettingsStore } from "@/lib/stores/mail-settings-store"

type PersistedSettings = Pick<
  ReturnType<typeof useMailSettingsStore.getState>,
  | "density"
  | "themeMode"
  | "backgroundId"
  | "inboxSort"
  | "readingPane"
  | "conversationMode"
  | "desktopNewMail"
  | "desktopMentions"
  | "emailDigest"
  | "soundEnabled"
>

function pickPersisted(state: ReturnType<typeof useMailSettingsStore.getState>): PersistedSettings {
  return {
    density: state.density,
    themeMode: state.themeMode,
    backgroundId: state.backgroundId,
    inboxSort: state.inboxSort,
    readingPane: state.readingPane,
    conversationMode: state.conversationMode,
    desktopNewMail: state.desktopNewMail,
    desktopMentions: state.desktopMentions,
    emailDigest: state.emailDigest,
    soundEnabled: state.soundEnabled,
  }
}

function diffPersisted(
  prev: PersistedSettings,
  next: PersistedSettings
): Partial<PersistedSettings> {
  const changed: Partial<PersistedSettings> = {}
  if (prev.density !== next.density) changed.density = next.density
  if (prev.themeMode !== next.themeMode) changed.themeMode = next.themeMode
  if (prev.backgroundId !== next.backgroundId) changed.backgroundId = next.backgroundId
  if (prev.inboxSort !== next.inboxSort) changed.inboxSort = next.inboxSort
  if (prev.readingPane !== next.readingPane) changed.readingPane = next.readingPane
  if (prev.conversationMode !== next.conversationMode) {
    changed.conversationMode = next.conversationMode
  }
  if (prev.desktopNewMail !== next.desktopNewMail) changed.desktopNewMail = next.desktopNewMail
  if (prev.desktopMentions !== next.desktopMentions) {
    changed.desktopMentions = next.desktopMentions
  }
  if (prev.emailDigest !== next.emailDigest) changed.emailDigest = next.emailDigest
  if (prev.soundEnabled !== next.soundEnabled) changed.soundEnabled = next.soundEnabled
  return changed
}

export function MailSettingsSync() {
  const authenticated = useAuthStore((s) => s.isAuthenticated())
  const { data } = useMailSettings(authenticated)
  const updateMutation = useUpdateMailSettings()
  const hydratingRef = useRef(false)
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)
  const prevRef = useRef<PersistedSettings>(pickPersisted(useMailSettingsStore.getState()))

  useEffect(() => {
    if (!data) return
    hydratingRef.current = true
    const mapped = apiSettingsToStore(data)
    useMailSettingsStore.getState().hydrateFromApi(mapped)
    prevRef.current = pickPersisted(useMailSettingsStore.getState())
    queueMicrotask(() => {
      hydratingRef.current = false
    })
  }, [data])

  useEffect(() => {
    const unsub = useMailSettingsStore.subscribe((state) => {
      if (hydratingRef.current) return

      const next = pickPersisted(state)
      const changed = diffPersisted(prevRef.current, next)
      if (Object.keys(changed).length === 0) return

      prevRef.current = next
      if (debounceRef.current) clearTimeout(debounceRef.current)
      debounceRef.current = setTimeout(() => {
        updateMutation.mutate(storeSettingsToPatch(changed))
      }, 500)
    })

    return () => {
      unsub()
      if (debounceRef.current) clearTimeout(debounceRef.current)
    }
  }, [updateMutation])

  return null
}
