import { Button } from '@/components/ui/button'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
import { usePrimaryPage } from '@/contexts/primary-page-context'
import { buildHiveTalkJoinUrl, roomIdForPubkeys } from '@/lib/hivetalk'
import { getNostrArchivesProfileUrl, openExternalUrl } from '@/lib/link'
import { pubkeyToNpub } from '@/lib/pubkey'
import { useMuteList } from '@/contexts/mute-list-context'
import { muteSetHas } from '@/lib/mute-set'
import { normalizeAnyRelayUrl } from '@/lib/url'
import { useNostr } from '@/providers/NostrProvider'
import { useCurrentRelays } from '@/providers/CurrentRelaysProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import { FAST_READ_RELAY_URLS, FAST_WRITE_RELAY_URLS } from '@/constants'
import { encodeProfileInteractionsSpellId } from '@/pages/primary/SpellsPage/fauxSpellConfig'
import client, { replaceableEventService } from '@/services/client.service'
import { nip66Service } from '@/services/nip66.service'
import RawEventDialog from '@/components/NoteOptions/RawEventDialog'
import {
  Bell,
  BellOff,
  Code,
  Copy,
  Ellipsis,
  ExternalLink,
  Flag,
  ThumbsUp,
  MessageCircle,
  Network,
  Send,
  SatelliteDish,
  Video
} from 'lucide-react'
import { useMemo, useState, useEffect } from 'react'
import { createReactionDraftEvent } from '@/lib/draft-event'
import PostEditor from '@/components/PostEditor'
import { showSimplePublishSuccess, toastPublishPromise } from '@/lib/publishing-feedback'
import { useTranslation } from 'react-i18next'
import { toast } from 'sonner'
import { Event, kinds } from 'nostr-tools'

export default function ProfileOptions({
  pubkey,
  profileEvent,
  onSendPublicMessage,
  onSendCallInvite,
  onSeeReports
}: {
  pubkey: string
  /** Optional profile event (kind 0): reply / like, republish to relays, view JSON */
  profileEvent?: Event
  /** Opens the post editor in public message mode with this profile's pubkey in the mention list. */
  onSendPublicMessage?: () => void
  /** Opens the post editor to send the call invite URL as a public message to this profile. */
  onSendCallInvite?: (url: string) => void
  /** Opens the profile reports modal. */
  onSeeReports?: () => void
}) {
  const { t } = useTranslation()
  const { navigate } = usePrimaryPage()
  const { pubkey: accountPubkey, publish, checkLogin } = useNostr()
  const { mutePubkeySet, mutePubkeyPrivately, mutePubkeyPublicly, unmutePubkey } = useMuteList()
  const { relayUrls: currentBrowsingRelayUrls } = useCurrentRelays()
  const { relaySets, favoriteRelays } = useFavoriteRelays()
  const [isRawEventDialogOpen, setIsRawEventDialogOpen] = useState(false)
  const [openReply, setOpenReply] = useState(false)
  const [reacting, setReacting] = useState(false)
  const [monitoringListRelayCount, setMonitoringListRelayCount] = useState<number | null>(null)
  const [localProfileEvent, setLocalProfileEvent] = useState<Event | undefined>(profileEvent)
  
  // Fetch profile event if not provided
  useEffect(() => {
    if (profileEvent) {
      setLocalProfileEvent(profileEvent)
      return
    }
    
    // If profileEvent is not provided, try to fetch it using comprehensive search
    const fetchEvent = async () => {
      try {
        // Use fetchProfileEvent which includes comprehensive relay search
        const event = await replaceableEventService.fetchProfileEvent(pubkey, false, {
          allowWideRelayFallback: true
        })
        if (event) {
          setLocalProfileEvent(event)
        }
      } catch {
        // Silently fail: reply/like stay hidden until the event loads
      }
    }
    
    fetchEvent()
  }, [pubkey, profileEvent])
  
  const isMuted = useMemo(() => muteSetHas(mutePubkeySet, pubkey), [mutePubkeySet, pubkey])
  const nostrArchivesProfileUrl = useMemo(() => getNostrArchivesProfileUrl(pubkey), [pubkey])

  /** All available relays: current feed, favorites, relay sets, defaults (FAST_READ, FAST_WRITE). */
  const allAvailableRelayUrls = useMemo(() => {
    const urls = [
      ...currentBrowsingRelayUrls.map((url) => normalizeAnyRelayUrl(url) || url),
      ...favoriteRelays.map((url) => normalizeAnyRelayUrl(url) || url),
      ...relaySets.flatMap((set) => set.relayUrls.map((url) => normalizeAnyRelayUrl(url) || url)),
      ...FAST_READ_RELAY_URLS.map((url) => normalizeAnyRelayUrl(url) || url),
      ...FAST_WRITE_RELAY_URLS.map((url) => normalizeAnyRelayUrl(url) || url)
    ].filter(Boolean) as string[]
    return Array.from(new Set(urls))
  }, [currentBrowsingRelayUrls, favoriteRelays, relaySets])

  useEffect(() => {
    void nip66Service.getPublicLivelyRelayUrls().then((urls) => {
      setMonitoringListRelayCount(urls?.length ?? 0)
    })
  }, [])

  const eventToUse = localProfileEvent || profileEvent
  /** Kind 0 only; coerce `kind` in case deserialization yields a string. */
  const kind0ForRelay =
    eventToUse != null && Number(eventToUse.kind) === kinds.Metadata ? eventToUse : undefined

  const handleRepublishToAllAvailable = async () => {
    if (!kind0ForRelay) {
      toast.error(t('Profile event not available'))
      return
    }
    const promise = client.publishEvent(allAvailableRelayUrls, kind0ForRelay, { skipOutboxRetry: true }).then((result) => {
      if (result.successCount < 1) {
        throw new Error(t('No relay accepted the event'))
      }
      return result
    })
    toastPublishPromise(promise, {
      loading: t('Republishing...'),
      success: () => t('Successfully republish to all available relays'),
      error: (err) => t('Failed to republish to all available relays: {{error}}', { error: err.message })
    })
  }

  const handleRepublishToAllActive = async () => {
    if (!kind0ForRelay) {
      toast.error(t('Profile event not available'))
      return
    }
    const promise = (async () => {
      let relays = await nip66Service.getPublicLivelyRelayUrls()
      const usedMonitoringList = !!relays?.length
      if (!relays?.length) {
        relays = allAvailableRelayUrls
      }
      if (!relays?.length) {
        throw new Error(t('No relays available'))
      }
      const result = await client.publishEvent(relays, kind0ForRelay, { skipOutboxRetry: true })
      const minRequired = usedMonitoringList ? 5 : 1
      if (result.successCount < minRequired) {
        throw new Error(
          usedMonitoringList
            ? t('Only {{count}} relay(s) accepted the event; at least 5 required for "all active relays".', {
                count: result.successCount
              })
            : t('No relay accepted the event')
        )
      }
      return result
    })()
    toastPublishPromise(promise, {
      loading: t('Republishing...'),
      success: () => t('Successfully republish to all active relays'),
      error: (err) => t('Failed to republish to all active relays: {{error}}', { error: err.message })
    })
  }

  const handleLike = () => {
    if (!eventToUse) return
    checkLogin(async () => {
      if (reacting) return
      setReacting(true)
      try {
        const reaction = createReactionDraftEvent(eventToUse, '+')
        const evt = await publish(reaction)
        if (evt) {
          showSimplePublishSuccess(t('Reaction published'))
        }
      } finally {
        setReacting(false)
      }
    })
  }

  if (pubkey === accountPubkey) return null

  const callInviteUrl =
    accountPubkey &&
    buildHiveTalkJoinUrl({ room: roomIdForPubkeys(accountPubkey, pubkey) })

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="secondary" size="icon" className="rounded-full">
          <Ellipsis />
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent>
        {eventToUse && (
          <>
            <DropdownMenuItem onClick={() => setOpenReply(true)}>
              <MessageCircle />
              {t('Reply')}
            </DropdownMenuItem>
            <DropdownMenuItem onClick={handleLike} disabled={reacting}>
              <ThumbsUp />
              {reacting ? t('Publishing...') : t('Like')}
            </DropdownMenuItem>
            <DropdownMenuSeparator />
          </>
        )}
        {onSendPublicMessage && (
          <DropdownMenuItem onClick={onSendPublicMessage}>
            <MessageCircle />
            {t('Send public message')}
          </DropdownMenuItem>
        )}
        {callInviteUrl && (
          <>
            <DropdownMenuSeparator />
            <DropdownMenuItem
              onClick={() => window.open(callInviteUrl, '_blank', 'noopener,noreferrer')}
            >
              <Video />
              {t('Start video call')}
            </DropdownMenuItem>
            <DropdownMenuItem
              onClick={() => {
                navigator.clipboard.writeText(callInviteUrl)
                toast.success(t('Copied to clipboard'))
              }}
            >
              <Copy />
              {t('Copy call invite link')}
            </DropdownMenuItem>
            {onSendCallInvite && (
              <DropdownMenuItem onClick={() => onSendCallInvite(callInviteUrl)}>
                <Send />
                {t('Send call invite')}
              </DropdownMenuItem>
            )}
            <DropdownMenuSeparator />
          </>
        )}
        <DropdownMenuItem
          onClick={() => navigator.clipboard.writeText('nostr:' + pubkeyToNpub(pubkey))}
        >
          <Copy />
          {t('Copy user ID')}
        </DropdownMenuItem>
        <DropdownMenuItem onClick={() => navigate('spells', { spell: encodeProfileInteractionsSpellId(pubkey) })}>
          <Network />
          {t('Interactions map')}
        </DropdownMenuItem>
        {onSeeReports && (
          <DropdownMenuItem onClick={onSeeReports}>
            <Flag />
            {t('See reports')}
          </DropdownMenuItem>
        )}
        {nostrArchivesProfileUrl && (
          <DropdownMenuItem onClick={() => openExternalUrl(nostrArchivesProfileUrl)}>
            <ExternalLink />
            {t('View on Nostr.Archives')}
          </DropdownMenuItem>
        )}
        {kind0ForRelay && (
          <>
            <DropdownMenuSeparator />
            <DropdownMenuItem onClick={handleRepublishToAllAvailable}>
              <SatelliteDish />
              {t('Republish to all available relays')} ({allAvailableRelayUrls.length})
            </DropdownMenuItem>
            <DropdownMenuItem onClick={handleRepublishToAllActive}>
              <SatelliteDish />
              {t('Republish to all active relays')}
              {monitoringListRelayCount !== null &&
                ` (${monitoringListRelayCount > 0 ? monitoringListRelayCount : allAvailableRelayUrls.length})`}
            </DropdownMenuItem>
            <DropdownMenuItem onClick={() => setIsRawEventDialogOpen(true)}>
              <Code />
              {t('View JSON')}
            </DropdownMenuItem>
          </>
        )}
        {isMuted ? (
          <DropdownMenuItem
            onClick={() => unmutePubkey(pubkey)}
            className="text-destructive focus:text-destructive"
          >
            <Bell />
            {t('Unmute user')}
          </DropdownMenuItem>
        ) : (
          <>
            <DropdownMenuItem
              onClick={() => mutePubkeyPrivately(pubkey)}
              className="text-destructive focus:text-destructive"
            >
              <BellOff />
              {t('Mute user privately')}
            </DropdownMenuItem>
            <DropdownMenuItem
              onClick={() => mutePubkeyPublicly(pubkey)}
              className="text-destructive focus:text-destructive"
            >
              <BellOff />
              {t('Mute user publicly')}
            </DropdownMenuItem>
          </>
        )}
      </DropdownMenuContent>
        {eventToUse && (
          <PostEditor
            parentEvent={eventToUse}
            open={openReply}
            setOpen={setOpenReply}
          />
        )}
        {kind0ForRelay && (
          <RawEventDialog
            event={kind0ForRelay}
            isOpen={isRawEventDialogOpen}
            onClose={() => setIsRawEventDialogOpen(false)}
          />
        )}
    </DropdownMenu>
  )
}
