import { Skeleton } from '@/components/ui/skeleton'
import { ExtendedKind, isNip71StyleVideoKind } from '@/constants'
import {
  notificationReactionSummaryKey,
  useNotificationReactionDisplay
} from '@/hooks/useNotificationReactionDisplay'
import { isMentioningMutedUsers, isNip18RepostKind, isNip25ReactionKind } from '@/lib/event'
import {
  DISCUSSION_DOWNVOTE_DISPLAY,
  DISCUSSION_UPVOTE_DISPLAY
} from '@/lib/discussion-votes'
import { getWebBookmarkArticleUrl } from '@/lib/rss-article'
import { cn } from '@/lib/utils'
import { useContentPolicyOptional } from '@/providers/ContentPolicyProvider'
import { useMuteListOptional } from '@/contexts/mute-list-context'
import { muteSetHas } from '@/lib/mute-set'
import { mergeTranslatedNote, useNoteTranslation } from '@/lib/note-translation-display'
import { Event, kinds } from 'nostr-tools'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import CommunityDefinitionPreview from './CommunityDefinitionPreview'
import GroupMetadataPreview from './GroupMetadataPreview'
import HighlightPreview from './HighlightPreview'
import LiveEventPreview from './LiveEventPreview'
import LongFormArticlePreview from './LongFormArticlePreview'
import NormalContentPreview from './NormalContentPreview'
import PictureNotePreview from './PictureNotePreview'
import PollPreview from './PollPreview'
import VideoNotePreview from './VideoNotePreview'
import ZapPreview from './ZapPreview'
import DiscussionNote from '../DiscussionNote'
import ApplicationHandlerInfo from '../ApplicationHandlerInfo'
import ApplicationHandlerRecommendation from '../ApplicationHandlerRecommendation'
import FollowPackPreview from './FollowPackPreview'
import ReactionEmojiDisplay from '../Note/ReactionEmojiDisplay'
import NoteKindLabel from '../Note/NoteKindLabel'
import Zap from '../Note/Zap'
import GitRepublicEventCard from '../Note/GitRepublicEventCard'

/** Inert event so hooks can run before `event` is defined. */
const CONTENT_PREVIEW_HOOK_PLACEHOLDER = {
  kind: kinds.ShortTextNote,
  id: '',
  pubkey: '',
  content: '',
  tags: [],
  created_at: 0,
  sig: ''
} as Event

const PARENT_REPLY_POLL_BLURB_MAX = 150

function parentReplyPollQuestionBlurb(content: string): string {
  const normalized = content.trim().replace(/\s+/g, ' ')
  if (normalized.length <= PARENT_REPLY_POLL_BLURB_MAX) return normalized
  return `${normalized.slice(0, PARENT_REPLY_POLL_BLURB_MAX)}…`
}

/** Keep spacing/margins on the outer wrapper; put line-clamp on the preview body so it still clamps text. */
function splitPreviewLayoutClasses(className?: string) {
  if (!className?.trim()) return { outer: undefined, body: undefined }
  const tokens = className.trim().split(/\s+/)
  const body: string[] = []
  const outer: string[] = []
  for (const tok of tokens) {
    if (tok.startsWith('line-clamp')) body.push(tok)
    else outer.push(tok)
  }
  return {
    outer: outer.length ? outer.join(' ') : undefined,
    body: body.length ? body.join(' ') : undefined
  }
}

export default function ContentPreview({
  event,
  className,
  /** Inline parent lines (e.g. reply thread): zap receipts match compact thread styling. */
  previewDensity,
  /** Reply-to-parent strip: polls show a short question snippet instead of full poll UI. */
  forParentReplyBlurb = false
}: {
  event?: Event
  className?: string
  previewDensity?: 'default' | 'compact'
  forParentReplyBlurb?: boolean
}) {
  const { t } = useTranslation()
  const noteTr = useNoteTranslation(event?.id ?? '')
  const reactionDisplay = useNotificationReactionDisplay(event ?? CONTENT_PREVIEW_HOOK_PLACEHOLDER)
  const muteList = useMuteListOptional()
  const mutePubkeySet = muteList?.mutePubkeySet ?? new Set<string>()
  const contentPolicy = useContentPolicyOptional()
  const hideContentMentioningMutedUsers = contentPolicy?.hideContentMentioningMutedUsers ?? false
  const isMuted = useMemo(
    () => (event ? muteSetHas(mutePubkeySet, event.pubkey) : false),
    [mutePubkeySet, event]
  )
  const isMentioningMuted = useMemo(
    () =>
      hideContentMentioningMutedUsers && event
        ? isMentioningMutedUsers(event, mutePubkeySet)
        : false,
    [event, mutePubkeySet]
  )

  if (!event) {
    return <div className={cn('pointer-events-none', className)}>{`[${t('Note not found')}]`}</div>
  }

  if (isMuted) {
    return (
      <div className={cn('pointer-events-none', className)}>[{t('This user has been muted')}]</div>
    )
  }

  if (isMentioningMuted) {
    return (
      <div className={cn('pointer-events-none', className)}>
        [{t('This note mentions a user you muted')}]
      </div>
    )
  }

  const previewEvent = mergeTranslatedNote(event, noteTr)

  const { outer: previewOuter, body: previewBody } = splitPreviewLayoutClasses(className)

  const withKindRow = (node: React.ReactNode) => (
    <div className={cn('flex min-w-0 flex-col gap-1', previewOuter)}>
      <NoteKindLabel kind={previewEvent.kind} event={previewEvent} size="small" />
      <div className={cn('min-w-0', previewBody)}>{node}</div>
    </div>
  )

  if (
    [
      kinds.ShortTextNote,
      ExtendedKind.COMMENT,
      ExtendedKind.VOICE,
      ExtendedKind.VOICE_COMMENT,
      ExtendedKind.RELAY_REVIEW,
      ExtendedKind.PUBLIC_MESSAGE
    ].includes(event.kind)
  ) {
    return withKindRow(<NormalContentPreview event={previewEvent} />)
  }

  if (event.kind === ExtendedKind.DISCUSSION) {
    return (
      <div className={cn('flex min-w-0 flex-col gap-1', previewOuter)}>
        <NoteKindLabel kind={previewEvent.kind} event={previewEvent} size="small" />
        <div className={cn('min-w-0', previewBody)}>
          <DiscussionNote event={previewEvent} size="small" />
        </div>
      </div>
    )
  }

  if (event.kind === kinds.Highlights) {
    return withKindRow(<HighlightPreview event={previewEvent} />)
  }

  if (event.kind === ExtendedKind.WEB_BOOKMARK) {
    const href = getWebBookmarkArticleUrl(previewEvent)
    const title = previewEvent.tags.find((t) => t[0] === 'title')?.[1]?.trim()
    const line = title?.trim() || href?.trim() || t('Web bookmark')
    return withKindRow(<div className={cn('min-w-0 truncate text-sm', previewBody)}>{line}</div>)
  }

  if (event.kind === ExtendedKind.POLL) {
    if (forParentReplyBlurb) {
      const snippet = parentReplyPollQuestionBlurb(previewEvent.content ?? '')
      return (
        <div className={cn('pointer-events-none min-w-0 text-muted-foreground', previewOuter)}>
          <div className={cn('min-w-0 truncate', previewBody)}>{snippet || t('Poll')}</div>
        </div>
      )
    }
    return withKindRow(<PollPreview event={previewEvent} />)
  }

  if (event.kind === kinds.LongFormArticle) {
    return withKindRow(<LongFormArticlePreview event={previewEvent} />)
  }

  if (isNip71StyleVideoKind(event.kind)) {
    return withKindRow(<VideoNotePreview event={previewEvent} />)
  }

  if (event.kind === ExtendedKind.PICTURE) {
    return withKindRow(<PictureNotePreview event={previewEvent} />)
  }

  if (event.kind === ExtendedKind.GROUP_METADATA) {
    return withKindRow(<GroupMetadataPreview event={previewEvent} />)
  }

  if (event.kind === kinds.CommunityDefinition) {
    return withKindRow(<CommunityDefinitionPreview event={previewEvent} />)
  }

  if (event.kind === kinds.LiveEvent) {
    return withKindRow(<LiveEventPreview event={previewEvent} />)
  }

  if (event.kind === ExtendedKind.ZAP_REQUEST) {
    return withKindRow(<ZapPreview event={previewEvent} />)
  }

  if (event.kind === ExtendedKind.ZAP_RECEIPT || event.kind === kinds.Zap) {
    if (previewDensity === 'compact') {
      return (
        <div className={cn('min-w-0', previewOuter)}>
          <Zap event={previewEvent} variant="compact" omitSenderHeading className={previewBody} />
        </div>
      )
    }
    return withKindRow(<ZapPreview event={previewEvent} />)
  }

  if (event.kind === ExtendedKind.APPLICATION_HANDLER_INFO) {
    return withKindRow(<ApplicationHandlerInfo event={previewEvent} />)
  }

  if (event.kind === ExtendedKind.APPLICATION_HANDLER_RECOMMENDATION) {
    return withKindRow(<ApplicationHandlerRecommendation event={previewEvent} />)
  }

  if (event.kind === ExtendedKind.FOLLOW_PACK) {
    return withKindRow(<FollowPackPreview event={previewEvent} />)
  }

  if (
    event.kind === ExtendedKind.GIT_REPO_ANNOUNCEMENT ||
    event.kind === ExtendedKind.GIT_ISSUE ||
    event.kind === ExtendedKind.GIT_RELEASE
  ) {
    return withKindRow(<GitRepublicEventCard variant="compact" event={previewEvent} />)
  }

  if (isNip25ReactionKind(event.kind)) {
    return withKindRow(
      <div className="pointer-events-none flex items-center gap-1.5 text-sm text-muted-foreground">
        {reactionDisplay.status === 'pending' ? (
          <Skeleton className="size-4 shrink-0 rounded-sm" aria-hidden />
        ) : reactionDisplay.status === 'vote_up' ? (
          <span className="text-base leading-none" aria-hidden>
            {DISCUSSION_UPVOTE_DISPLAY}
          </span>
        ) : reactionDisplay.status === 'vote_down' ? (
          <span className="text-base leading-none" aria-hidden>
            {DISCUSSION_DOWNVOTE_DISPLAY}
          </span>
        ) : (
          <ReactionEmojiDisplay event={previewEvent} maxRawLength={24} variant="compact" />
        )}
        {t(notificationReactionSummaryKey(reactionDisplay))}
      </div>
    )
  }

  if (isNip18RepostKind(event.kind)) {
    return withKindRow(
      <div className="pointer-events-none text-sm text-muted-foreground">{t('Notification boost summary')}</div>
    )
  }

  if (event.kind === ExtendedKind.POLL_RESPONSE) {
    return withKindRow(
      <div className="pointer-events-none text-sm text-muted-foreground">
        {t('Notification poll vote summary')}
      </div>
    )
  }

  return withKindRow(<div>[{t('Cannot handle event of kind k', { k: previewEvent.kind })}]</div>)
}
