import {
	CompleteMultipartUploadCommand,
	CreateMultipartUploadCommand,
	S3Client,
	UploadPartCommand,
} from '@aws-sdk/client-s3'
import { InjectAws } from '@backend/aws'
import { Logger } from '@nestjs/common'
import { MulterFile } from 'nestjs-busboy'
import { OnEvent } from '@nestjs/event-emitter'

export interface FileUploadEventOptions {
	bucket: string
	uploadPath: string
	file: MulterFile
}

export class FileUploadConsumer {
	private readonly logger = new Logger(FileUploadConsumer.name)

	constructor(@InjectAws(S3Client) private readonly _s3Client: S3Client) {}

	@OnEvent('storage.upload')
	async upload(options: FileUploadEventOptions): Promise<void> {
		try {
			const createUploadCommand = new CreateMultipartUploadCommand({
				Bucket: options.bucket,
				Key: options.uploadPath,
				ContentType: options.file.mimetype,
				ACL: 'public-read',
			})
			const createUploadResult = await this._s3Client.send(createUploadCommand)

			const uploadPartCommand = new UploadPartCommand({
				Bucket: options.bucket,
				Key: options.uploadPath,
				PartNumber: 1,
				UploadId: createUploadResult.UploadId,
				Body: options.file.buffer,
				ContentLength: options.file.buffer?.length,
			})
			const uploadPartResult = await this._s3Client.send(uploadPartCommand)

			const completeUploadCommand = new CompleteMultipartUploadCommand({
				Bucket: options.bucket,
				Key: options.uploadPath,
				UploadId: createUploadResult.UploadId,
				MultipartUpload: { Parts: [{ ETag: uploadPartResult.ETag, PartNumber: 1 }] },
			})
			await this._s3Client.send(completeUploadCommand)

			this.logger.log(`File ${options.uploadPath} uploaded to S3`)
		} catch (error) {
			this.logger.error({ message: 'Failed to upload file to S3', error })
		}
	}
}
