import { ref } from 'vue'
import type { NostrNote } from '@/lib/nostr/client'
import { createTextNote, createReaction, createProfileMetadata } from '@/lib/nostr/events'
import { identity } from '@/composables/useIdentity'
import { toast } from 'vue-sonner'

import { useNostr } from './useNostr'

export function useSocial(relayUrls?: string[]) {
  const { getClient } = useNostr(relayUrls ? { relays: relayUrls } : undefined)
  const client = getClient()
  const isPublishing = ref(false)
  const profiles = ref(new Map<string, any>())

  /**
   * Publish a text note
   */
  async function publishNote(content: string, replyTo?: string): Promise<void> {
    if (!identity.isAuthenticated.value || !identity.currentIdentity.value) {
      throw new Error('Must be logged in to publish notes')
    }

    try {
      isPublishing.value = true
      
      await client.connect()
      const event = createTextNote(content, identity.currentIdentity.value, replyTo)
      await client.publishEvent(event)
      
      toast.success(replyTo ? 'Reply published!' : 'Note published!')
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Failed to publish note'
      toast.error(message)
      throw error
    } finally {
      isPublishing.value = false
    }
  }

  /**
   * Publish a reaction to a note
   */
  async function publishReaction(targetEventId: string, targetAuthor: string, reaction: string = '👍'): Promise<void> {
    if (!identity.isAuthenticated.value || !identity.currentIdentity.value) {
      throw new Error('Must be logged in to react to notes')
    }

    try {
      await client.connect()
      const event = createReaction(targetEventId, targetAuthor, reaction, identity.currentIdentity.value)
      await client.publishEvent(event)
      
      toast.success('Reaction added!')
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Failed to add reaction'
      toast.error(message)
      throw error
    }
  }

  /**
   * Publish profile metadata
   */
  async function publishProfile(profileData: any): Promise<void> {
    if (!identity.isAuthenticated.value || !identity.currentIdentity.value) {
      throw new Error('Must be logged in to update profile')
    }

    try {
      isPublishing.value = true
      
      await client.connect()
      const event = createProfileMetadata(profileData, identity.currentIdentity.value)
      await client.publishEvent(event)
      
      toast.success('Profile updated on Nostr!')
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Failed to update profile'
      toast.error(message)
      throw error
    } finally {
      isPublishing.value = false
    }
  }

  /**
   * Fetch replies to a note
   */
  async function fetchReplies(noteId: string): Promise<NostrNote[]> {
    try {
      await client.connect()
      return await client.fetchReplies(noteId)
    } catch (error) {
      console.error('Failed to fetch replies:', error)
      throw error
    }
  }

  /**
   * Fetch and cache user profiles
   */
  async function fetchProfiles(pubkeys: string[]): Promise<void> {
    // Filter out already cached profiles
    const uncachedPubkeys = pubkeys.filter(pubkey => !profiles.value.has(pubkey))
    
    if (uncachedPubkeys.length === 0) return

    try {
      await client.connect()
      const fetchedProfiles = await client.fetchProfiles(uncachedPubkeys)
      
      // Update cache
      fetchedProfiles.forEach((profile, pubkey) => {
        profiles.value.set(pubkey, profile)
      })
    } catch (error) {
      console.error('Failed to fetch profiles:', error)
    }
  }

  /**
   * Get cached profile or return default
   */
  function getProfile(pubkey: string) {
    return profiles.value.get(pubkey) || {
      name: pubkey.slice(0, 8) + '...',
      display_name: undefined,
      about: undefined,
      picture: undefined
    }
  }

  /**
   * Get display name for a pubkey
   */
  function getDisplayName(pubkey: string): string {
    const profile = getProfile(pubkey)
    return profile.display_name || profile.name || pubkey.slice(0, 8) + '...'
  }

  return {
    // State
    isPublishing,
    profiles,

    // Actions
    publishNote,
    publishReaction,
    publishProfile,
    fetchReplies,
    fetchProfiles,
    getProfile,
    getDisplayName
  }
}

// Export singleton instance for global use
export const social = useSocial()