import { Injectable, BadRequestException, Logger } from '@nestjs/common';
import { v2 as cloudinary, UploadApiErrorResponse, UploadApiResponse } from 'cloudinary';
import * as streamifier from 'streamifier';


@Injectable()
export class FileUploadService {
  private readonly logger = new Logger(FileUploadService.name);

  private getUploadConfig(fileName: string, folderName: string) {
    const baseConfig = {
      resource_type: 'auto' as const,
      use_filename: true,
      unique_filename: true,
      public_id: fileName,
    };

    return {
      ...baseConfig,
      folder: `dfuk/${folderName}`,
    };
  }

  private createFileName(file: Express.Multer.File): string {
    const timestamp = Date.now();
    return `${timestamp}-${file.originalname
      .split(' ')
      .join('-')
      .replace(/\.[^/.]+$/, '')}`;
  }

  private uploadToCloudinary(file: Express.Multer.File, folderName: string): Promise<string> {
    if (!file) {
      throw new BadRequestException(`No file provided`);
    }

    if (!file.buffer) {
      throw new BadRequestException(`Invalid file format`);
    }

    return new Promise((resolve, reject) => {
      try {
        const fileName = this.createFileName(file);
        const uploadConfig = this.getUploadConfig(fileName, folderName);
        const stream = streamifier.createReadStream(file.buffer);

        const uploadStream = cloudinary.uploader.upload_stream(
          uploadConfig,
          (error: UploadApiErrorResponse | undefined, result: UploadApiResponse | undefined) => {
            if (error) {
              reject(new BadRequestException(`Failed to upload to cloudinary: ${error.message}`));
              return;
            }

            if (!result?.secure_url) {
              reject(new BadRequestException(`Failed to get secure URL for uploaded file`));
              return;
            }

            resolve(result.secure_url);
          },
        );

        stream.pipe(uploadStream).on('error', error => {
          reject(new BadRequestException(`Failed to process stream for upload: ${error.message}`));
        });
      } catch (error) {
        this.logger.error(`Unexpected error in upload`, error);
        reject(new BadRequestException(`Unexpected error during  upload: ${error.message}`));
      }
    });
  }

  async uploadImageToCloudinary(file: Express.Multer.File, folderName: string): Promise<string> {
    return this.uploadToCloudinary(file, folderName);
  }
}
