import {type ReportReason} from '@crumbs/core/schemas'
import {useRouter} from 'expo-router'

import {useBusyAction} from '@/hooks/use-busy-action'
import {
  alertError,
  alertInfo,
  confirmDestructive,
  showActionSheet,
} from '@/lib/dialogs'
import {useOpenConversation} from '@/stores/dms'
import {
  useBlockUser,
  useLoadFriends,
  useRefreshRequests,
  useReportUser,
  useSendFriendRequest,
  useUnblockUser,
  useUnfriend,
} from '@/stores/friends'
import {useLoadProfile, type ProfileDetail} from '@/stores/profile'

const REPORT_REASONS: {label: string; reason: ReportReason}[] = [
  {label: 'Spam', reason: 'spam'},
  {label: 'Harassment', reason: 'harassment'},
  {label: 'Inappropriate content', reason: 'inappropriate'},
  {label: 'Something else', reason: 'other'},
]

// the profile header's social actions — add/accept friend, open a dm,
// unfriend, block/unblock and report — each owning its busy state and
// alerting failures
export const useProfileActions = (
  userId: string,
  profile: ProfileDetail | undefined,
) => {
  const router = useRouter()
  const sendRequest = useSendFriendRequest()
  const loadFriends = useLoadFriends()
  const refreshRequests = useRefreshRequests()
  const openConversation = useOpenConversation()
  const unfriend = useUnfriend()
  const blockUser = useBlockUser()
  const unblockUser = useUnblockUser()
  const reportUser = useReportUser()
  const loadProfile = useLoadProfile()
  const {busy: addingId, run: runAdd} = useBusyAction({haptic: false})
  const {busy: messagingId, run: runMessage} = useBusyAction({
    haptic: false,
  })

  // the shared shape of every social mutation: apply it, then reload the
  // profile so friendship status reflects the change, alerting failures
  const mutateProfile = async (mutate: () => Promise<unknown>) => {
    try {
      await mutate()
      await loadProfile(userId)
    } catch (err) {
      alertError(err)
    }
  }

  const onAddFriend = () =>
    runAdd(userId, async () => {
      await sendRequest(userId)
      await Promise.all([
        loadProfile(userId),
        loadFriends(),
        refreshRequests(),
      ])
    })

  const onMessage = () =>
    runMessage(userId, async () => {
      const conversationId = await openConversation(userId)
      router.push(`/dms/${conversationId}`)
    })

  const onUnfriend = async () => {
    if (!profile) return
    const ok = await confirmDestructive({
      title: `Unfriend @${profile.handle}?`,
      message:
        'You will no longer see each other’s crumbs and trails.',
      actionLabel: 'Unfriend',
    })
    if (ok) await mutateProfile(() => unfriend(userId))
  }

  const onBlock = async () => {
    if (!profile) return
    const ok = await confirmDestructive({
      title: `Block @${profile.handle}?`,
      message:
        'They won’t be able to find you, message you, or see your crumbs and trails. You can unblock anytime.',
      actionLabel: 'Block',
    })
    if (ok) await mutateProfile(() => blockUser(userId))
  }

  const onUnblock = () => mutateProfile(() => unblockUser(userId))

  const submitReport = async (reason: ReportReason) => {
    try {
      await reportUser({
        subjectType: 'user',
        subjectId: userId,
        reason,
      })
      alertInfo('Report received', 'Thanks — we’ll review this.')
    } catch (err) {
      alertError(err)
    }
  }

  const onReport = () => {
    if (!profile) return
    showActionSheet(
      REPORT_REASONS.map(({label, reason}) => ({
        label,
        onPress: () => void submitReport(reason),
      })),
      {title: `Report @${profile.handle}`},
    )
  }

  const showProfileMenu = () => {
    const status = profile?.friendshipStatus
    showActionSheet([
      ...(status === 'friends'
        ? [
            {
              label: 'Unfriend',
              destructive: true,
              onPress: () => void onUnfriend(),
            },
          ]
        : []),
      ...(status === 'blocked'
        ? [{label: 'Unblock', onPress: () => void onUnblock()}]
        : [
            {
              label: 'Block',
              destructive: true,
              onPress: () => void onBlock(),
            },
          ]),
      {label: 'Report', onPress: onReport},
    ])
  }

  return {
    busy: addingId !== null,
    messaging: messagingId !== null,
    onAddFriend,
    onMessage,
    onUnblock,
    showProfileMenu,
  }
}
