// useStatusKind — Phase B §3.1 of the Mastodon follow-up plan.
//
// Pixelfed enriches Mobilizon events server-side with `pf_type='event'` and
// a `pf_event` sidecar. Vanilla Mastodon strips the extension on federation,
// so a Mastodon-active client sees Mobilizon events as plain text/photo
// statuses. To still surface them as events, we classify the author's host
// via nodeinfo and trust `software.name === 'mobilizon'` as the event signal.
//
// Returns 'event' on:
//   - Pixelfed accounts when `pf_type === 'event'` (existing path).
//   - Mastodon accounts when the author's host is a Mobilizon instance.
// Returns 'default' otherwise.
//
// The Mastodon-side probe runs lazily: on first sight of an unknown author
// host the cache is empty, so the hook returns 'default' and schedules the
// nodeinfo round-trip. When the cache write lands, an MMKV listener flips
// the hook's local state and a re-render picks up 'event'. No loading state
// in the cell — opportunistic enrichment, not a category.

import { useEffect, useState } from 'react'
import type { Status } from 'src/lib/api-types'
import { classifyRemoteHost, getCachedSoftwareName } from 'src/lib/instance-software'
import { useAuth } from 'src/state/AuthProvider'
import { appStorage } from 'src/state/storage'
import { getDomain } from 'src/utils'

export type StatusKind = 'event' | 'default'

const MOBILIZON_HOST_CACHE_PREFIX = 'app.softwareByHost.'

function authorHost(status: Status | null | undefined): string | null {
  // `account.url` is the canonical actor URL on the originating instance —
  // for federated actors that's the foreign host, which is exactly what we
  // want to classify. `account.acct` is host-suffixed only for remote
  // actors, so it would silently misclassify local-instance Mobilizon
  // bridges. The URL is the safer signal.
  const url = status?.account?.url
  if (!url) return null
  try {
    return getDomain(url)
  } catch {
    return null
  }
}

export function useStatusKind(status: Status | null | undefined): StatusKind {
  const { user } = useAuth()
  const isMastodon = user?.type === 'mastodon'
  const host = isMastodon ? authorHost(status) : null

  // The Mastodon-side cache lookup: initial state from MMKV synchronously,
  // then an effect below subscribes to the per-host cache key and updates
  // when the deferred probe writes. Hooks run unconditionally so the
  // Pixelfed branch below stays rules-of-hooks-safe even though it never
  // consults the resolved value.
  const [mastodonKind, setMastodonKind] = useState<StatusKind>(() => {
    if (!host) return 'default'
    return getCachedSoftwareName(host) === 'mobilizon' ? 'event' : 'default'
  })

  useEffect(() => {
    if (!host) return

    const apply = (name: string | null | undefined) => {
      setMastodonKind(name === 'mobilizon' ? 'event' : 'default')
    }

    const cached = getCachedSoftwareName(host)
    if (cached === undefined) {
      // Unknown host — fire-and-forget classification. Resolution writes
      // through MMKV; the listener below catches the write and flips state.
      classifyRemoteHost(host).catch(() => {})
    } else {
      apply(cached)
    }

    const key = `${MOBILIZON_HOST_CACHE_PREFIX}${host}`
    const sub = appStorage.addOnValueChangedListener((changed) => {
      if (changed !== key) return
      apply(appStorage.getString(key))
    })
    return () => sub.remove()
  }, [host])

  if (!isMastodon) {
    // Pixelfed: lean on the existing server-side enrichment. The Mastodon
    // state above is computed regardless (rules of hooks) but ignored.
    return status?.pf_type === 'event' ? 'event' : 'default'
  }

  return mastodonKind
}
