import {confirmDestructive, showActionSheet} from '@/lib/dialogs'
import {
  discardMutation,
  discardRemovesEntity,
  discardScope,
  mutationRemovesEntity,
  redriveMutation,
  redriveScope,
} from '@/stores/outbox'

// the failed-sync affordance every surface shares: retry from scratch, or
// discard. discarding permanently drops the write and rolls back its
// optimistic effect (possibly a whole offline-created entity), so it is
// always confirmed first, like every other destructive action

// human titles for the outbox kinds the ui knows; unknown kinds fall back
// to the raw kind rather than hiding a change
const KIND_TITLES: Record<string, string> = {
  'crumb.create': 'New crumb',
  'crumb.update': 'Edited crumb',
  'crumb.delete': 'Deleted crumb',
  'dm.send': 'Message',
  'trail.create': 'New trail',
  'trail.update': 'Edited trail',
  'trail.delete': 'Deleted trail',
  'trail.post.create': 'New post',
  'trail.post.delete': 'Deleted post',
  'trail.react': 'Reaction',
  'trail.pin': 'Pin',
  'trail.crumb.add': 'Added to trail',
  'trail.crumb.remove': 'Removed from trail',
  'trail.crumb.move': 'Reordered trail',
  'crumb.image': 'Crumb photo',
  'trail.cover': 'Trail cover',
  avatar: 'Profile photo',
  handle: 'Handle',
}

export const outboxKindTitle = (kind: string): string =>
  KIND_TITLES[kind] ?? kind

const confirmDiscard = (removesEntity: boolean): Promise<boolean> =>
  confirmDestructive({
    title: 'Discard change?',
    message: removesEntity
      ? 'This never finished syncing, so discarding will remove it.'
      : 'The unsynced change will be permanently discarded.',
    actionLabel: 'Discard',
  })

// scope-level: an entity screen's failed badge (a crumb, a trail).
// onEntityDiscarded fires only when the discard removed the entity itself
// (a dead create), so the screen leaves exactly when its subject is gone
export const showSyncMenu = (
  id: string,
  {onEntityDiscarded}: {onEntityDiscarded?: () => void} = {},
): void =>
  showActionSheet([
    {label: 'Retry sync', onPress: () => redriveScope(id)},
    {
      label: 'Discard change',
      destructive: true,
      onPress: () => {
        void (async () => {
          const removesEntity = discardRemovesEntity(id)
          if (!(await confirmDiscard(removesEntity))) return
          discardScope(id)
          if (removesEntity) onEntityDiscarded?.()
        })()
      },
    },
  ])

// entry-level twin for a row that maps one-to-one to a mutation (a dm
// bubble): the same retry/discard pair keyed by the entry id
export const showEntrySyncMenu = (id: string): void =>
  showActionSheet([
    {label: 'Retry sync', onPress: () => redriveMutation(id)},
    {
      label: 'Discard change',
      destructive: true,
      onPress: () => void confirmDiscardMutation(id),
    },
  ])

export const confirmDiscardMutation = async (
  id: string,
): Promise<void> => {
  if (!(await confirmDiscard(mutationRemovesEntity(id)))) return
  discardMutation(id)
}
