import {pickTagEmoji} from '@crumbs/core/emojis'
import type {Crumb, UpdateCrumbInput} from '@crumbs/core/schemas'

import {type Draft} from '@/lib/draft'

// a best-effort local render of a crumb created offline: enough shape to show
// in lists and detail the instant it's saved, and CrumbSchema-valid so it
// survives a snapshot round-trip across a cold start. server-derived fields
// (an unresolved place, image, canonical timestamps) fill in when the queued
// create replays and the server copy replaces it by id. tags reuse the shared
// emoji map so an offline crumb's tags read identically to a synced one
export const optimisticCrumb = (
  draft: Draft,
  tags: string[],
  {id, authorId, now}: {id: string; authorId: string; now: string},
): Crumb => ({
  id,
  authorId,
  name: draft.name,
  note: draft.note,
  imageUrl: null,
  source: draft.source,
  status: 'saved',
  plannedFor: null,
  // an already-resolved place renders now; an unresolved target (a geocoder
  // ref or free-form hints) stays null until the create syncs
  place: draft.place ?? null,
  event: null,
  origin: null,
  tags: tags.map((name) => ({name, emoji: pickTagEmoji(name)})),
  createdAt: now,
  updatedAt: now,
})

// apply an edit's changed fields onto a crumb for an optimistic render. only
// fields the client can resolve locally are touched — a place change needs the
// server, so the existing place stays until the edit syncs. tags reuse the
// shared emoji map so they match the server
export const applyOptimisticUpdate = (
  crumb: Crumb,
  input: UpdateCrumbInput,
  now: string,
): Crumb => ({
  ...crumb,
  ...(input.name !== undefined && {name: input.name}),
  ...(input.note !== undefined && {note: input.note ?? null}),
  ...(input.status !== undefined && {status: input.status}),
  ...(input.plannedFor !== undefined && {
    plannedFor: input.plannedFor ?? null,
  }),
  ...(input.tags !== undefined && {
    tags: input.tags.map((name) => ({
      name,
      emoji: pickTagEmoji(name),
    })),
  }),
  updatedAt: now,
})
