// server/utils/blurHash.ts
import sharp from 'sharp'
import { encode } from 'blurhash'
import { $fetch } from 'ofetch'
import { mkdir, writeFile, unlink } from 'node:fs/promises'
import { join } from 'node:path'
import { tmpdir } from 'node:os'
import { randomUUID } from 'node:crypto'

// Dossier temporaire pour les images téléchargées
const TMP_DIR = join(tmpdir(), 'evilspins-images')

async function ensureTmpDir() {
  try {
    await mkdir(TMP_DIR, { recursive: true })
  } catch (error) {
    if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error
  }
}

async function downloadImage(url: string): Promise<string> {
  await ensureTmpDir()
  const tmpPath = join(TMP_DIR, `${randomUUID()}.jpg`)

  try {
    const response = await $fetch(url, {
      responseType: 'arrayBuffer',
      headers: {
        'User-Agent':
          'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        Accept: 'image/*,*/*;q=0.8'
      },
      // Timeout plus long
      timeout: 60000, // 60 secondes
      // Désactiver la compression pour les images
      headers: {
        'Accept-Encoding': 'identity'
      }
    })

    await writeFile(tmpPath, Buffer.from(response))
    return tmpPath
  } catch (error) {
    // Nettoyer en cas d'erreur
    try {
      await unlink(tmpPath).catch(() => {})
    } catch {
      /* Ignorer les erreurs de suppression */
    }
    console.error(`Failed to download image from ${url}:`, error.message)
    throw error
  }
}

function createDefaultBlurhash() {
  // Un blurhash plus discret
  return 'L5H2EC=H00~q^-=wD6xuxvV@%KxZ'
}

export async function generateBlurhash(
  input: Buffer | string,
  componentX: number = 4,
  componentY: number = 3
): Promise<string> {
  let tmpPath: string | null = null

  try {
    if (typeof input === 'string') {
      if (input.startsWith('http')) {
        try {
          tmpPath = await downloadImage(input)
          input = tmpPath
        } catch (error) {
          console.warn(`Using default blurhash for ${input} due to download error`)
          return createDefaultBlurhash()
        }
      }

      // Vérifier si le fichier existe
      try {
        const image = sharp(input).resize(32, 32, { fit: 'inside' }).ensureAlpha()

        const { data, info } = await image.raw().toBuffer({ resolveWithObject: true })
        return encode(new Uint8ClampedArray(data), info.width, info.height, componentX, componentY)
      } catch (error) {
        console.warn(`Error processing image ${input}:`, error.message)
        return createDefaultBlurhash()
      }
    } else {
      // Si c'est déjà un Buffer
      try {
        const image = sharp(input).resize(32, 32, { fit: 'inside' }).ensureAlpha()

        const { data, info } = await image.raw().toBuffer({ resolveWithObject: true })
        return encode(new Uint8ClampedArray(data), info.width, info.height, componentX, componentY)
      } catch (error) {
        console.warn('Error processing image buffer:', error.message)
        return createDefaultBlurhash()
      }
    }
  } catch (error) {
    console.error('Unexpected error in generateBlurhash:', error.message)
    return createDefaultBlurhash()
  } finally {
    // Nettoyer le fichier temporaire s'il existe
    if (tmpPath) {
      try {
        await unlink(tmpPath).catch(() => {})
      } catch {
        /* Ignorer les erreurs de suppression */
      }
    }
  }
}
