/**
 * NDK Event Publishing Patterns
 * 
 * Examples from: src/publish/orders.tsx, scripts/gen_products.ts
 */

import NDK, { NDKEvent, NDKTag } from '@nostr-dev-kit/ndk'

// ============================================================
// BASIC EVENT PUBLISHING
// ============================================================

const publishBasicNote = async (ndk: NDK, content: string) => {
  // Create event
  const event = new NDKEvent(ndk)
  event.kind = 1  // Text note
  event.content = content
  event.tags = []
  
  // Sign and publish
  await event.sign()
  await event.publish()
  
  console.log('✅ Published note:', event.id)
  return event.id
}

// ============================================================
// EVENT WITH TAGS
// ============================================================

const publishNoteWithTags = async (
  ndk: NDK,
  content: string,
  options: {
    mentions?: string[]  // pubkeys to mention
    hashtags?: string[]
    replyTo?: string     // event ID
  }
) => {
  const event = new NDKEvent(ndk)
  event.kind = 1
  event.content = content
  event.tags = []
  
  // Add mentions
  if (options.mentions) {
    options.mentions.forEach(pubkey => {
      event.tags.push(['p', pubkey])
    })
  }
  
  // Add hashtags
  if (options.hashtags) {
    options.hashtags.forEach(tag => {
      event.tags.push(['t', tag])
    })
  }
  
  // Add reply
  if (options.replyTo) {
    event.tags.push(['e', options.replyTo, '', 'reply'])
  }
  
  await event.sign()
  await event.publish()
  
  return event.id
}

// ============================================================
// PRODUCT LISTING (PARAMETERIZED REPLACEABLE EVENT)
// ============================================================

interface ProductData {
  slug: string           // Unique identifier
  title: string
  description: string
  price: number
  currency: string
  images: string[]
  shippingRefs?: string[]
  category?: string
}

const publishProduct = async (ndk: NDK, product: ProductData) => {
  const event = new NDKEvent(ndk)
  event.kind = 30402  // Product listing kind
  event.content = product.description
  
  // Build tags
  event.tags = [
    ['d', product.slug],                    // Unique identifier (required for replaceable)
    ['title', product.title],
    ['price', product.price.toString(), product.currency],
  ]
  
  // Add images
  product.images.forEach(image => {
    event.tags.push(['image', image])
  })
  
  // Add shipping options
  if (product.shippingRefs) {
    product.shippingRefs.forEach(ref => {
      event.tags.push(['shipping', ref])
    })
  }
  
  // Add category
  if (product.category) {
    event.tags.push(['t', product.category])
  }
  
  // Optional: set custom timestamp
  event.created_at = Math.floor(Date.now() / 1000)
  
  await event.sign()
  await event.publish()
  
  console.log('✅ Published product:', product.title)
  return event.id
}

// ============================================================
// ORDER CREATION EVENT
// ============================================================

interface OrderData {
  orderId: string
  sellerPubkey: string
  productRef: string
  quantity: number
  totalAmount: string
  currency: string
  shippingRef?: string
  shippingAddress?: string
  email?: string
  phone?: string
  notes?: string
}

const createOrder = async (ndk: NDK, order: OrderData) => {
  const event = new NDKEvent(ndk)
  event.kind = 16  // Order processing kind
  event.content = order.notes || ''
  
  // Required tags per spec
  event.tags = [
    ['p', order.sellerPubkey],
    ['subject', `Order ${order.orderId.substring(0, 8)}`],
    ['type', 'order-creation'],
    ['order', order.orderId],
    ['amount', order.totalAmount],
    ['item', order.productRef, order.quantity.toString()],
  ]
  
  // Optional tags
  if (order.shippingRef) {
    event.tags.push(['shipping', order.shippingRef])
  }
  
  if (order.shippingAddress) {
    event.tags.push(['address', order.shippingAddress])
  }
  
  if (order.email) {
    event.tags.push(['email', order.email])
  }
  
  if (order.phone) {
    event.tags.push(['phone', order.phone])
  }
  
  try {
    await event.sign()
    await event.publish()
    
    console.log('✅ Order created:', order.orderId)
    return { success: true, eventId: event.id }
  } catch (error) {
    console.error('❌ Failed to create order:', error)
    return { success: false, error }
  }
}

// ============================================================
// STATUS UPDATE EVENT
// ============================================================

const publishStatusUpdate = async (
  ndk: NDK,
  orderId: string,
  recipientPubkey: string,
  status: 'pending' | 'paid' | 'shipped' | 'delivered' | 'cancelled',
  notes?: string
) => {
  const event = new NDKEvent(ndk)
  event.kind = 16
  event.content = notes || `Order status updated to ${status}`
  event.tags = [
    ['p', recipientPubkey],
    ['subject', 'order-info'],
    ['type', 'status-update'],
    ['order', orderId],
    ['status', status],
  ]
  
  await event.sign()
  await event.publish()
  
  return event.id
}

// ============================================================
// BATCH PUBLISHING
// ============================================================

const publishMultipleEvents = async (
  ndk: NDK,
  events: Array<{ kind: number; content: string; tags: NDKTag[] }>
) => {
  const results = []
  
  for (const eventData of events) {
    try {
      const event = new NDKEvent(ndk)
      event.kind = eventData.kind
      event.content = eventData.content
      event.tags = eventData.tags
      
      await event.sign()
      await event.publish()
      
      results.push({ success: true, eventId: event.id })
    } catch (error) {
      results.push({ success: false, error })
    }
  }
  
  return results
}

// ============================================================
// PUBLISH WITH CUSTOM SIGNER
// ============================================================

import { NDKSigner } from '@nostr-dev-kit/ndk'

const publishWithCustomSigner = async (
  ndk: NDK,
  signer: NDKSigner,
  eventData: { kind: number; content: string; tags: NDKTag[] }
) => {
  const event = new NDKEvent(ndk)
  event.kind = eventData.kind
  event.content = eventData.content
  event.tags = eventData.tags
  
  // Sign with specific signer (not ndk.signer)
  await event.sign(signer)
  await event.publish()
  
  return event.id
}

// ============================================================
// ERROR HANDLING PATTERN
// ============================================================

const publishWithErrorHandling = async (
  ndk: NDK,
  eventData: { kind: number; content: string; tags: NDKTag[] }
) => {
  // Validate NDK
  if (!ndk) {
    throw new Error('NDK not initialized')
  }
  
  // Validate signer
  if (!ndk.signer) {
    throw new Error('No active signer. Please login first.')
  }
  
  try {
    const event = new NDKEvent(ndk)
    event.kind = eventData.kind
    event.content = eventData.content
    event.tags = eventData.tags
    
    // Sign
    await event.sign()
    
    // Verify signature
    if (!event.sig) {
      throw new Error('Event signing failed')
    }
    
    // Publish
    await event.publish()
    
    // Verify event ID
    if (!event.id) {
      throw new Error('Event ID not generated')
    }
    
    return {
      success: true,
      eventId: event.id,
      pubkey: event.pubkey
    }
  } catch (error) {
    console.error('Publishing failed:', error)
    
    if (error instanceof Error) {
      // Handle specific error types
      if (error.message.includes('relay')) {
        throw new Error('Failed to publish to relays. Check connection.')
      }
      if (error.message.includes('sign')) {
        throw new Error('Failed to sign event. Check signer.')
      }
    }
    
    throw error
  }
}

// ============================================================
// USAGE EXAMPLE
// ============================================================

async function publishingExample(ndk: NDK) {
  // Simple note
  await publishBasicNote(ndk, 'Hello Nostr!')
  
  // Note with tags
  await publishNoteWithTags(ndk, 'Check out this product!', {
    hashtags: ['marketplace', 'nostr'],
    mentions: ['pubkey123...']
  })
  
  // Product listing
  await publishProduct(ndk, {
    slug: 'bitcoin-tshirt',
    title: 'Bitcoin T-Shirt',
    description: 'High quality Bitcoin t-shirt',
    price: 25,
    currency: 'USD',
    images: ['https://example.com/image.jpg'],
    category: 'clothing'
  })
  
  // Order
  await createOrder(ndk, {
    orderId: 'order-123',
    sellerPubkey: 'seller-pubkey',
    productRef: '30402:pubkey:bitcoin-tshirt',
    quantity: 1,
    totalAmount: '25.00',
    currency: 'USD',
    email: 'customer@example.com'
  })
}

export {
  publishBasicNote,
  publishNoteWithTags,
  publishProduct,
  createOrder,
  publishStatusUpdate,
  publishMultipleEvents,
  publishWithCustomSigner,
  publishWithErrorHandling
}

