/**
 * Blog-specific Image Plugin
 * Handles image upload to S3 when images are dragged/pasted into the editor
 */

import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { useEffect, useState } from 'react'
import { $insertNodes, COMMAND_PRIORITY_EDITOR, createCommand } from 'lexical'
import type { LexicalCommand } from 'lexical'
import { $createImageNode, ImageNode } from '../../editor/nodes/ImageNode'
import { uploadFile, getDownloadPresignedURL } from '../api'

export const INSERT_BLOG_IMAGE_COMMAND: LexicalCommand<File> = createCommand('INSERT_BLOG_IMAGE_COMMAND')

interface UploadingImage {
  id: string
  file: File
  localUrl: string
}

export function BlogImagePlugin() {
  const [editor] = useLexicalComposerContext()
  const [, setUploadingImages] = useState<Map<string, UploadingImage>>(new Map())

  useEffect(() => {
    if (!editor.hasNodes([ImageNode])) {
      throw new Error('BlogImagePlugin: ImageNode not registered on editor')
    }

    return editor.registerCommand(
      INSERT_BLOG_IMAGE_COMMAND,
      (file: File) => {
        const id = `uploading-${Date.now()}-${Math.random()}`
        const localUrl = URL.createObjectURL(file)

        // Add to uploading state
        setUploadingImages(prev => new Map(prev.set(id, { id, file, localUrl })))

        // Insert placeholder image node with loading state
        editor.update(() => {
          const imageNode = $createImageNode({
            src: localUrl,
            altText: file.name,
            maxWidth: 800,
          })
          $insertNodes([imageNode])
        })

        // Start upload
        handleImageUpload(file, id, localUrl)

        return true
      },
      COMMAND_PRIORITY_EDITOR
    )
  }, [editor])

  const handleImageUpload = async (file: File, uploadId: string, localUrl: string) => {
    try {
      // Upload file and get fileKey
      const fileKey = await uploadFile(file)

      // Get download URL
      const { url: downloadUrl } = await getDownloadPresignedURL({ fileKey })

      // Update the image node with the actual S3 URL
      editor.update(() => {
        const nodes = editor.getEditorState().read(() => {
          const allNodes: any[] = []
          editor.getEditorState()._nodeMap.forEach((node) => {
            if (node instanceof ImageNode && node.getSrc() === localUrl) {
              allNodes.push(node)
            }
          })
          return allNodes
        })

        nodes.forEach(node => {
          if (node instanceof ImageNode) {
            const writable = node.getWritable()
            writable.__src = downloadUrl
          }
        })
      })

      // Clean up
      URL.revokeObjectURL(localUrl)
      setUploadingImages(prev => {
        const next = new Map(prev)
        next.delete(uploadId)
        return next
      })

      // Show success notification
      showNotification('Image uploaded successfully', 'success')
    } catch (error) {
      console.error('Failed to upload image:', error)
      
      // Show error notification
      showNotification('Failed to upload image', 'error')

      // Clean up
      URL.revokeObjectURL(localUrl)
      setUploadingImages(prev => {
        const next = new Map(prev)
        next.delete(uploadId)
        return next
      })
    }
  }

  // Handle paste events
  useEffect(() => {
    return editor.registerCommand(
      // @ts-ignore - PASTE_COMMAND exists
      editor.PASTE_COMMAND || 'PASTE_COMMAND',
      (event: ClipboardEvent) => {
        const items = event.clipboardData?.items
        if (!items) return false

        for (let i = 0; i < items.length; i++) {
          const item = items[i]
          if (item.type.indexOf('image') !== -1) {
            event.preventDefault()
            const file = item.getAsFile()
            if (file) {
              editor.dispatchCommand(INSERT_BLOG_IMAGE_COMMAND, file)
            }
            return true
          }
        }

        return false
      },
      COMMAND_PRIORITY_EDITOR
    )
  }, [editor])

  return null
}

// Simple notification helper
function showNotification(message: string, type: 'success' | 'error') {
  // You can replace this with your preferred notification library
  // For now, just using a simple alert-like approach
  const event = new CustomEvent('app:notification', {
    detail: { message, type }
  })
  window.dispatchEvent(event)
  
  console.log(`[${type.toUpperCase()}] ${message}`)
}
