import { BaseService } from '@/core/base/BaseService'
import type { ServiceMetadata } from '@/core/base/BaseService'
import appConfig from '@/app.config'

export interface UploadedImage {
  alias: string
  delete_token: string
  details: {
    width: number
    height: number
    content_type: string
    created_at: number
  }
}

export interface ImageUploadOptions {
  maxSizeMB?: number
  acceptedTypes?: string[]
  generateThumbnail?: boolean
}

export interface ImageUrlOptions {
  thumbnail?: number
  resize?: number
  blur?: number
  crop?: string
  format?: 'webp' | 'jpg' | 'png'
}

/**
 * Service for handling image uploads to pict-rs
 * Provides centralized image management for all modules
 */
export class ImageUploadService extends BaseService {
  protected readonly metadata: ServiceMetadata = {
    name: 'ImageUploadService',
    version: '1.0.0',
    dependencies: ['ToastService']
  }

  private baseUrl: string = ''
  private maxFileSizeMB: number = 10
  private acceptedTypes: string[] = ['image/jpeg', 'image/png', 'image/webp', 'image/avif', 'image/gif']

  protected async onInitialize(): Promise<void> {
    // Get configuration from environment or app config
    const baseModuleConfig = appConfig.modules.base.config as any
    this.baseUrl = baseModuleConfig.imageUpload?.baseUrl ||
                   import.meta.env.VITE_PICTRS_BASE_URL ||
                   'https://img.mydomain.com'

    this.maxFileSizeMB = baseModuleConfig.imageUpload?.maxSizeMB || 10

    if (baseModuleConfig.imageUpload?.acceptedTypes) {
      this.acceptedTypes = baseModuleConfig.imageUpload.acceptedTypes
    }

    this.debug('ImageUploadService initialized with baseUrl:', this.baseUrl)

    // TODO: Explore using LNbits as a proxy service for pict-rs
    // This would provide several benefits:
    // - Unified authentication with wallet admin keys
    // - Consistent CORS handling through LNbits server
    // - Better integration with marketplace and events modules
    // - Potential for payment-gated image uploads
    // - Centralized image management through LNbits extensions
    // Implementation would involve creating an LNbits extension that proxies
    // pict-rs requests and potentially adds authentication/payment layers
  }

  /**
   * Upload a single image file to pict-rs
   */
  async uploadImage(file: File, options: ImageUploadOptions = {}): Promise<UploadedImage> {
    try {
      // Validate file
      this.validateFile(file, options)

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

      const response = await fetch(`${this.baseUrl}/image`, {
        method: 'POST',
        body: formData
      })

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({ msg: 'Upload failed' }))
        throw new Error(errorData.msg || `Upload failed with status ${response.status}`)
      }

      const data = await response.json()

      if (!data.files || data.files.length === 0) {
        throw new Error('No file information returned from upload')
      }

      const uploadedFile = data.files[0]

      // Show success toast
      this.toastService?.success(`Image uploaded successfully`)

      return {
        alias: uploadedFile.file,
        delete_token: uploadedFile.delete_token,
        details: uploadedFile.details
      }
    } catch (error) {
      // Let component handle user feedback for better UX control
      throw this.handleError(error, 'uploadImage')
    }
  }

  /**
   * Upload multiple images
   * Returns successful uploads and logs errors for component to handle
   */
  async uploadImages(files: File[], options: ImageUploadOptions = {}): Promise<{
    results: UploadedImage[]
    errors: Array<{ file: string; error: string }>
  }> {
    const results: UploadedImage[] = []
    const errors: Array<{ file: string; error: string }> = []

    for (const file of files) {
      try {
        const result = await this.uploadImage(file, options)
        results.push(result)
      } catch (error) {
        errors.push({
          file: file.name,
          error: error instanceof Error ? error.message : String(error)
        })
      }
    }

    // Return both successful uploads and errors for component to handle
    if (errors.length > 0) {
      this.debug('Some images failed to upload:', errors)
    }

    return { results, errors }
  }

  /**
   * Delete an uploaded image
   */
  async deleteImage(deleteToken: string, alias: string): Promise<void> {
    try {
      const response = await fetch(`${this.baseUrl}/image/delete/${deleteToken}/${alias}`, {
        method: 'DELETE'
      })

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({ msg: 'Delete failed' }))
        throw new Error(errorData.msg || `Delete failed with status ${response.status}`)
      }

      this.debug('Image deleted successfully:', alias)
    } catch (error) {
      // Let component handle user feedback for better UX control
      throw this.handleError(error, 'deleteImage')
    }
  }

  /**
   * Get the URL for an image with optional processing using pict-rs
   * Supports thumbnail, resize, blur, and crop transformations
   */
  getImageUrl(alias: string, options: ImageUrlOptions = {}): string {
    if (!alias) {
      return ''
    }

    // If alias is already a full URL, return it as-is to prevent double URLs
    if (alias.startsWith('http://') || alias.startsWith('https://')) {
      return alias
    }

    // Extract file ID in case alias contains URL parts
    const fileId = this.extractFileId(alias)

    // If no processing options specified, return original
    if (!options.thumbnail && !options.resize && !options.blur && !options.crop) {
      return `${this.baseUrl}/image/original/${fileId}`
    }

    // Build processing URL with specified options
    const format = options.format || 'webp'
    let url = `${this.baseUrl}/image/process.${format}?src=${fileId}`

    if (options.thumbnail) {
      url += `&thumbnail=${options.thumbnail}`
    } else if (options.resize) {
      url += `&resize=${options.resize}`
    }

    if (options.blur) {
      url += `&blur=${options.blur}`
    }

    if (options.crop) {
      url += `&crop=${options.crop}`
    }

    return url
  }

  /**
   * Get thumbnail URL for an image using pict-rs processing
   */
  getThumbnailUrl(alias: string, size = 256): string {
    if (!alias) {
      return ''
    }

    // Extract file ID if alias is a full URL
    let fileId = this.extractFileId(alias)

    // Use pict-rs thumbnail processing with webp format for better compression
    return `${this.baseUrl}/image/process.webp?src=${fileId}&thumbnail=${size}`
  }

  /**
   * Get resized URL for an image using pict-rs Lanczos2 filter (better quality than thumbnail)
   */
  getResizedUrl(alias: string, size = 800): string {
    if (!alias) {
      return ''
    }

    // Extract file ID if alias is a full URL
    let fileId = this.extractFileId(alias)

    // Use pict-rs resize processing with webp format for better compression
    return `${this.baseUrl}/image/process.webp?src=${fileId}&resize=${size}`
  }

  /**
   * Get blurred placeholder URL using pict-rs gaussian blur (useful for loading states)
   */
  getBlurredUrl(alias: string, blur = 5): string {
    if (!alias) {
      return ''
    }

    // Extract file ID if alias is a full URL
    let fileId = this.extractFileId(alias)

    // Use pict-rs blur processing with webp format
    return `${this.baseUrl}/image/process.webp?src=${fileId}&blur=${blur}`
  }

  /**
   * Get cropped URL for an image using pict-rs center crop (maintains aspect ratio)
   */
  getCroppedUrl(alias: string, width: number, height: number): string {
    if (!alias) {
      return ''
    }

    // Extract file ID if alias is a full URL
    let fileId = this.extractFileId(alias)

    // Use pict-rs crop processing with webp format
    return `${this.baseUrl}/image/process.webp?src=${fileId}&crop=${width}x${height}`
  }

  /**
   * Extract file ID from alias, handling both file IDs and full URLs
   */
  private extractFileId(alias: string): string {
    if (!alias) {
      return ''
    }

    // If it's already a file ID (not a full URL), return as-is
    if (!alias.startsWith('http://') && !alias.startsWith('https://')) {
      return alias
    }

    // Extract file ID from full pict-rs URL
    if (alias.includes('/image/original/')) {
      const parts = alias.split('/image/original/')
      if (parts.length > 1 && parts[1]) {
        return parts[1]
      }
    }

    // If we can't extract file ID, return the original alias
    return alias
  }

  /**
   * Validate file before upload
   */
  private validateFile(file: File, options: ImageUploadOptions = {}): void {
    const maxSize = (options.maxSizeMB || this.maxFileSizeMB) * 1024 * 1024
    const acceptedTypes = options.acceptedTypes || this.acceptedTypes

    // Check file type
    if (!acceptedTypes.includes(file.type)) {
      throw new Error(`Invalid file type: ${file.type}. Accepted types: ${acceptedTypes.join(', ')}`)
    }

    // Check file size
    if (file.size > maxSize) {
      const sizeMB = (file.size / (1024 * 1024)).toFixed(2)
      const maxMB = (maxSize / (1024 * 1024)).toFixed(0)
      throw new Error(`File size (${sizeMB}MB) exceeds maximum allowed size (${maxMB}MB)`)
    }
  }

  /**
   * Convert File to base64 for preview (client-side only)
   */
  async fileToBase64(file: File): Promise<string> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = () => resolve(reader.result as string)
      reader.onerror = error => reject(error)
    })
  }

  /**
   * Check if pict-rs server is available
   */
  async checkHealth(): Promise<boolean> {
    try {
      const response = await fetch(`${this.baseUrl}/healthz`, {
        method: 'GET',
        signal: AbortSignal.timeout(5000)
      })
      return response.ok
    } catch (error) {
      this.debug('pict-rs health check failed:', error)
      return false
    }
  }

  /**
   * Get service status information
   */
  getStatus(): {
    baseUrl: string
    maxFileSizeMB: number
    acceptedTypes: string[]
    isConfigured: boolean
  } {
    return {
      baseUrl: this.baseUrl,
      maxFileSizeMB: this.maxFileSizeMB,
      acceptedTypes: this.acceptedTypes,
      isConfigured: !!this.baseUrl && this.baseUrl !== 'https://img.mydomain.com'
    }
  }
}