import type { Editor } from '@tiptap/core'
import type { Media } from '@prisma/client'

export interface MediaHandlerOptions {
	editor: Editor
	albumId?: number
	features: {
		imageUpload?: boolean
		mediaLibrary?: boolean
	}
}

export class ComposerMediaHandler {
	private editor: Editor
	private albumId?: number
	private features: MediaHandlerOptions['features']

	constructor(options: MediaHandlerOptions) {
		this.editor = options.editor
		this.albumId = options.albumId
		this.features = options.features
	}

	async uploadImage(file: File): Promise<void> {
		if (!this.editor || !this.features.imageUpload) return

		// Validate file size (2MB max)
		const filesize = file.size / 1024 / 1024
		if (filesize > 2) {
			alert(`Image too large! File size: ${filesize.toFixed(2)} MB (max 2MB)`)
			return
		}

		// Create a placeholder while uploading
		const placeholderSrc = URL.createObjectURL(file)
		this.editor.commands.insertContent({
			type: 'image',
			attrs: {
				src: placeholderSrc,
				alt: '',
				title: '',
				mediaId: null
			}
		})

		try {
			const auth = localStorage.getItem('admin_auth')
			if (!auth) {
				throw new Error('Not authenticated')
			}

			const formData = new FormData()
			formData.append('file', file)

			// Add albumId if available
			if (this.albumId) {
				formData.append('albumId', this.albumId.toString())
			}

			const response = await fetch('/api/media/upload', {
				method: 'POST',
				headers: {
					Authorization: `Basic ${auth}`
				},
				body: formData
			})

			if (!response.ok) {
				throw new Error('Upload failed')
			}

			const media = await response.json()

			// Replace placeholder with actual URL
			const displayWidth = media.width && media.width > 600 ? 600 : media.width

			this.editor.commands.insertContent([
				{
					type: 'image',
					attrs: {
						src: media.url,
						alt: media.filename || '',
						title: media.description || '',
						width: displayWidth,
						height: media.height,
						align: 'center',
						mediaId: media.id?.toString()
					}
				},
				{
					type: 'paragraph'
				}
			])

			// Clean up the object URL
			URL.revokeObjectURL(placeholderSrc)
		} catch (error) {
			console.error('Image upload failed:', error)
			alert('Failed to upload image. Please try again.')
			// Remove the placeholder on error
			this.editor.commands.undo()
			URL.revokeObjectURL(placeholderSrc)
		}
	}

	handleMediaSelect(media: Media): void {
		if (!this.editor) return

		// Remove placeholder if it exists
		if (this.editor.storage.imageModal?.placeholderPos !== undefined) {
			const pos = this.editor.storage.imageModal.placeholderPos
			this.editor
				.chain()
				.focus()
				.deleteRange({ from: pos, to: pos + 1 })
				.run()
			this.editor.storage.imageModal.placeholderPos = undefined
		}

		// Check if it's a video
		const isVideo = media.mimeType?.startsWith('video/')

		if (isVideo) {
			// Insert video
			this.editor.commands.insertContent({
				type: 'video',
				attrs: {
					src: media.url,
					title: media.description || media.filename || '',
					mediaId: media.id.toString()
				}
			})
		} else {
			// Calculate display dimensions
			const displayWidth = media.width && media.width > 600 ? 600 : media.width

			// Insert image
			this.editor.commands.insertContent([
				{
					type: 'image',
					attrs: {
						src: media.url,
						alt: media.filename || '',
						title: media.description || '',
						width: displayWidth,
						height: media.height,
						align: 'center',
						mediaId: media.id.toString()
					}
				},
				{
					type: 'paragraph'
				}
			])
		}
	}

	handleMediaClose(): void {
		// Remove the placeholder if user cancelled
		if (this.editor && this.editor.storage.imageModal?.placeholderPos !== undefined) {
			const pos = this.editor.storage.imageModal.placeholderPos
			this.editor
				.chain()
				.focus()
				.deleteRange({ from: pos, to: pos + 1 })
				.run()
			this.editor.storage.imageModal.placeholderPos = undefined
		}
	}

	handlePasteImage(clipboardData: DataTransfer): boolean {
		if (!this.features.imageUpload) return false

		// Check for images
		const imageItem = Array.from(clipboardData.items).find(
			(item) => item.type.indexOf('image') === 0
		)

		if (imageItem) {
			const file = imageItem.getAsFile()
			if (!file) return false

			// Upload the image
			this.uploadImage(file)
			return true // Prevent default paste behavior
		}

		return false
	}
}
