import { useQuery } from '@tanstack/react-query'
import { router } from 'expo-router'
import { useCallback, useState } from 'react'
import { useScreenMenu } from 'src/components/menu'
import { editPostMedia, getStatusById, putEditPost } from 'src/lib/api'
import { cameraQueries } from 'src/lib/queries/camera'
import { postQueries } from 'src/lib/queries/posts'
import { emit } from 'src/lib/tapestry/emit'

// Mirrors the useThreadActions / useComposer playbook: own the screen's state
// + mutations + menu intent in one place so the screen file stays a shell.
//
// The two things this hook deliberately does NOT manage: layout and
// presentation. It returns values the screen wires into Tamagui inputs.

type EditMedia = {
  id: string
  description: string
  // retaining loose shape — server payload has many unused fields and we
  // only round-trip what we edit.
  [key: string]: unknown
}

export function usePostEdit(id: string) {
  const [caption, setCaption] = useState('')
  const [isSensitive, setSensitive] = useState(false)
  const [media, setMedia] = useState<EditMedia[]>([])
  const [spoilerText, setSpoilerText] = useState('')
  const [showSpoiler, setShowSpoiler] = useState(false)
  const [isSaving, setSaving] = useState(false)

  const post = useQuery({
    queryKey: postQueries.detail(id).queryKey,
    queryFn: async () => {
      const res = await getStatusById(id)
      setCaption(res?.content_text)
      setSensitive(res?.sensitive)
      setMedia(res?.media_attachments)
      setSpoilerText(res?.spoiler_text)
      return res
    },
  })

  const instance = useQuery({
    ...cameraQueries.instance(),
    enabled: !!post.data,
  })

  const updateMediaAlt = useCallback((itemId: string, text: string) => {
    setMedia((prev) =>
      prev.map((m) => (m.id === itemId ? { ...m, description: text } : m))
    )
  }, [])

  const save = useCallback(async () => {
    const source = post.data
    if (!source) return
    setSaving(true)

    const originalMedia = source.media_attachments ?? []
    const mediaChanges = media.filter((m) => {
      const original = originalMedia.find((og: any) => og.id === m.id)
      return original && m.description !== original.description
    })

    try {
      await Promise.all(mediaChanges.map((m) => editPostMedia(m.id, m.description)))
      await putEditPost(source.id, {
        status: caption,
        sensitive: isSensitive,
        media_ids: media.map((m) => m.id),
      })
      emit('M')
    } finally {
      setSaving(false)
      router.back()
    }
  }, [post.data, media, caption, isSensitive])

  useScreenMenu({
    title: 'Edit Post',
    intents: [
      {
        kind: 'commit',
        id: 'save',
        icon: 'check',
        label: 'Save post',
        onPress: save,
        state: isSaving ? 'busy' : 'idle',
      },
    ],
  })

  const maxCharacters: number | undefined =
    instance.data?.configuration.statuses.max_characters

  return {
    // data / status
    post: post.data,
    isPending: post.isPending || instance.isPending,
    isLoading: post.isLoading,
    isError: post.isError,
    error: post.error,
    maxCharacters,

    // form state
    caption,
    setCaption,
    isSensitive,
    setSensitive,
    spoilerText,
    setSpoilerText,
    showSpoiler,
    setShowSpoiler,
    media,
    updateMediaAlt,

    // lifecycle
    isSaving,
    save,
  }
}
