import { useEffect, useRef } from 'react'
import { acct, asList, apiGet } from '../api/client'
import { ENDPOINTS, ACCOUNTING_ENDPOINTS } from '../api/config'
import type { ApiCustomer, ApiOwner } from '../api/types'
import type { Party } from '../types'
import { useStore } from '../store/AppStore'
import { createId } from '../utils/id'
import { findExistingParty, mergeFunZoneParties, partyNeedsSync } from './funzonePartySync'

/** Syncs FunZone owners/customers into accounting parties on app load. */
export function GlobalPartySync() {
  const { ready, upsertPartyAsync } = useStore()
  const synced = useRef(false)

  useEffect(() => {
    if (!ready || synced.current) return
    synced.current = true

    const run = async () => {
      try {
        const [owners, customersRaw, initialParties] = await Promise.all([
          apiGet<unknown>(ENDPOINTS.OWNERS).then(asList<ApiOwner>),
          apiGet<unknown>(ENDPOINTS.CUSTOMERS),
          acct.get(ACCOUNTING_ENDPOINTS.PARTIES).then(asList<Party>),
        ])

        const customers: ApiCustomer[] = Array.isArray(customersRaw)
          ? (customersRaw as ApiCustomer[])
          : ((customersRaw as { results?: ApiCustomer[] }).results ?? [])

        let currentParties = initialParties
        const batches = [
          ...mergeFunZoneParties(owners, currentParties, 'supplier'),
          ...mergeFunZoneParties(customers, currentParties, 'customer'),
        ]

        for (const incoming of batches) {
          const existing = findExistingParty(currentParties, incoming.externalId!, incoming.externalSource)
          if (existing && !partyNeedsSync(existing, incoming)) continue
          const next = { ...incoming, id: existing?.id ?? createId('party-') }
          await upsertPartyAsync(next)
          // Keep the local snapshot in sync so later comparisons in this pass don't re-PATCH.
          currentParties = existing
            ? currentParties.map((p) => (p.id === existing.id ? { ...p, ...next } : p))
            : [...currentParties, next]
        }
        // upsertPartyAsync already updates AppStore; avoid a full reload that re-fetches every resource.
      } catch {
        synced.current = false
      }
    }

    void run()
  }, [ready, upsertPartyAsync])

  return null
}
