import { v2 as cloudinary } from 'cloudinary';
import { S3Client, PutObjectCommand, GetObjectCommand, HeadObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

// Configuration Cloudinary
cloudinary.config({
  cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
  api_key: process.env.CLOUDINARY_API_KEY,
  api_secret: process.env.CLOUDINARY_API_SECRET,
  secure: true,
});

// Client S3 pour stocker les images converties
const s3Client = new S3Client({
  region: process.env.AWS_REGION || 'eu-west-3',
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  },
});

const S3_BUCKET = process.env.AWS_S3_BUCKET || 'odentas-docs';

interface PageImage {
  pageNumber: number;
  imageUrl: string;
  width: number;
  height: number;
}

/**
 * Vérifie si les images d'un PDF existent déjà dans S3
 */
async function checkImagesExistInS3(requestId: string): Promise<PageImage[] | null> {
  try {
    // On essaie de trouver les images existantes
    // On commence par vérifier la page 1
    const firstPageKey = `odentas-sign-images/${requestId}/page-1.jpg`;
    
    try {
      await s3Client.send(new HeadObjectCommand({
        Bucket: S3_BUCKET,
        Key: firstPageKey,
      }));
    } catch (error) {
      // La première page n'existe pas, donc les images ne sont pas en cache
      return null;
    }

    console.log('[S3 Cache] Images trouvées dans S3, récupération...');

    // La page 1 existe, on récupère toutes les pages
    const pageImages: PageImage[] = [];
    let pageNum = 1;
    
    while (true) {
      const s3Key = `odentas-sign-images/${requestId}/page-${pageNum}.jpg`;
      
      try {
        // Vérifier si la page existe
        await s3Client.send(new HeadObjectCommand({
          Bucket: S3_BUCKET,
          Key: s3Key,
        }));

        // Générer l'URL presignée
        const command = new GetObjectCommand({
          Bucket: S3_BUCKET,
          Key: s3Key,
        });
        const s3Url = await getSignedUrl(s3Client, command, { expiresIn: 86400 });

        pageImages.push({
          pageNumber: pageNum,
          imageUrl: s3Url,
          width: 1400,
          height: Math.round(1400 * 1.414),
        });

        pageNum++;
      } catch (error) {
        // Plus de pages, on sort de la boucle
        break;
      }
    }

    console.log(`[S3 Cache] ✅ ${pageImages.length} page(s) récupérées depuis S3 (pas de conversion)`);
    return pageImages.length > 0 ? pageImages : null;
  } catch (error) {
    console.log('[S3 Cache] Pas de cache trouvé, conversion nécessaire');
    return null;
  }
}

/**
 * Convertit un PDF en images JPEG via Cloudinary, 
 * puis stocke les images sur S3 pour économiser la bande passante Cloudinary
 */
export async function convertPdfToImagesWithCloudinary(
  pdfBuffer: Buffer,
  requestId: string
): Promise<PageImage[]> {
  try {
    // 1. Vérifier si les images existent déjà dans S3
    const cachedImages = await checkImagesExistInS3(requestId);
    if (cachedImages) {
      console.log('[S3 Cache] ✅ Utilisation du cache S3, pas de conversion Cloudinary');
      return cachedImages;
    }

    console.log('[Cloudinary] Pas de cache S3, début conversion...');
    console.log('[Cloudinary] Début upload PDF, taille:', pdfBuffer.length);

    // 1. Upload le PDF sur Cloudinary pour conversion
    const uploadResult = await new Promise<any>((resolve, reject) => {
      const uploadStream = cloudinary.uploader.upload_stream(
        {
          folder: `odentas-sign-temp/${requestId}`,
          resource_type: 'image',
          format: 'jpg',
          public_id: `pdf-${requestId}`,
          transformation: [
            { width: 1400, crop: 'scale' },
            { quality: 90 },
          ],
        },
        (error, result) => {
          if (error) reject(error);
          else resolve(result);
        }
      );

      uploadStream.end(pdfBuffer);
    });

    console.log('[Cloudinary] Upload réussi, conversion en cours...');

    const baseUrl = uploadResult.secure_url;
    const pages = uploadResult.pages || 1;

    const pageImages: PageImage[] = [];

    // 2. Pour chaque page, télécharger l'image depuis Cloudinary et la stocker sur S3
    for (let pageNum = 1; pageNum <= pages; pageNum++) {
      // URL Cloudinary de la page
      const cloudinaryPageUrl = baseUrl.replace(
        '/upload/',
        `/upload/pg_${pageNum}/w_1400,q_90/`
      );

      console.log(`[Cloudinary] Téléchargement page ${pageNum}/${pages} depuis Cloudinary...`);

      // Télécharger l'image depuis Cloudinary
      const imageResponse = await fetch(cloudinaryPageUrl);
      if (!imageResponse.ok) {
        throw new Error(`Erreur téléchargement page ${pageNum}: ${imageResponse.statusText}`);
      }

      const imageBuffer = Buffer.from(await imageResponse.arrayBuffer());

      // 3. Stocker l'image sur S3
      const s3Key = `odentas-sign-images/${requestId}/page-${pageNum}.jpg`;
      await s3Client.send(
        new PutObjectCommand({
          Bucket: S3_BUCKET,
          Key: s3Key,
          Body: imageBuffer,
          ContentType: 'image/jpeg',
          CacheControl: 'public, max-age=31536000', // Cache 1 an
        })
      );

      // Générer une URL presignée S3 (valide 24h, renouvelée à chaque accès)
      const command = new GetObjectCommand({
        Bucket: S3_BUCKET,
        Key: s3Key,
      });
      const s3Url = await getSignedUrl(s3Client, command, { expiresIn: 86400 }); // 24h

      pageImages.push({
        pageNumber: pageNum,
        imageUrl: s3Url,
        width: 1400,
        height: Math.round(1400 * 1.414), // Ratio A4
      });

      console.log(`[Cloudinary → S3] Page ${pageNum}/${pages} stockée sur S3: ${s3Key}`);
    }

    // 4. Nettoyer Cloudinary (supprimer le PDF temporaire)
    try {
      await cloudinary.uploader.destroy(`odentas-sign-temp/${requestId}/pdf-${requestId}`);
      console.log('[Cloudinary] Nettoyage temporaire effectué');
    } catch (cleanupError) {
      console.warn('[Cloudinary] Erreur nettoyage (non bloquant):', cleanupError);
    }

    console.log(`[Cloudinary → S3] ✅ ${pages} page(s) converties et stockées sur S3`);
    return pageImages;
  } catch (error) {
    console.error('[Cloudinary] Erreur:', error);
    throw new Error(
      `Erreur Cloudinary: ${error instanceof Error ? error.message : 'Erreur inconnue'}`
    );
  }
}

/**
 * Supprime un PDF et ses pages de Cloudinary
 */
export async function deleteFromCloudinary(requestId: string): Promise<void> {
  try {
    await cloudinary.api.delete_resources_by_prefix(`odentas-sign/${requestId}`);
    console.log(`[Cloudinary] PDF ${requestId} supprimé`);
  } catch (error) {
    console.error('[Cloudinary] Erreur suppression:', error);
  }
}
