"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var FileS3StorageProvider_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileS3StorageProvider = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("@nestjs/config");
const common_entity_1 = require("../../entities/common.entity");
const legacy_common_entity_1 = require("../../entities/legacy-common.entity");
const legacy_common_with_id_entity_1 = require("../../entities/legacy-common-with-id.entity");
const file_1 = require("../file");
const media_repository_1 = require("../../repository/media.repository");
let FileS3StorageProvider = FileS3StorageProvider_1 = class FileS3StorageProvider {
    constructor(configService, diskFileService, s3FileService, mediaRepository) {
        this.configService = configService;
        this.diskFileService = diskFileService;
        this.s3FileService = s3FileService;
        this.mediaRepository = mediaRepository;
        this.logger = new common_1.Logger(FileS3StorageProvider_1.name);
    }
    storeStreams(streamPairs, entity, mediaFieldMetadata) {
        throw new Error("Method not implemented.");
    }
    async retrieve(entity, mediaFieldMetadata) {
        const isSupportedEntity = entity instanceof common_entity_1.CommonEntity
            || entity instanceof legacy_common_entity_1.LegacyCommonEntity
            || entity instanceof legacy_common_with_id_entity_1.LegacyCommonWithIdEntity;
        if (!isSupportedEntity) {
            throw new Error("Entity must be an instance of CommonEntity, LegacyCommonEntity or LegacyCommonWithIdEntity");
        }
        const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);
        for (const m of media) {
            const storageMeta = m.mediaStorageProviderMetadata;
            const region = this.getEffectiveRegion(storageMeta.region);
            if (storageMeta.isPublic === false) {
                const expiryInSeconds = (storageMeta.signedUrlExpiry ?? 60) * 60;
                m['_full_url'] = await this.s3FileService.getUrl(`${storageMeta?.bucketName}:${m.relativeUri}`, { expiresIn: expiryInSeconds, region });
            }
            else {
                m['_full_url'] = this.getFullFilePath(m);
            }
        }
        return media;
    }
    async store(files, entity, mediaFieldMetadata) {
        const isSupportedEntity = entity instanceof common_entity_1.CommonEntity
            || entity instanceof legacy_common_entity_1.LegacyCommonEntity
            || entity instanceof legacy_common_with_id_entity_1.LegacyCommonWithIdEntity;
        if (!isSupportedEntity) {
            throw new Error("Entity must be an instance of CommonEntity, LegacyCommonEntity or LegacyCommonWithIdEntity");
        }
        const result = [];
        const storageProvider = mediaFieldMetadata.mediaStorageProvider;
        const region = this.getEffectiveRegion(storageProvider.region);
        for (const file of files) {
            const fileName = this.getFileName(file);
            const bucketName = storageProvider.bucketName;
            const fileData = await this.diskFileService.read(file.path);
            await this.s3FileService.write(`${bucketName}:${fileName}`, fileData, { contentType: file.mimetype, region });
            await this.diskFileService.delete(file.path);
            const awsFileUrl = fileName;
            const mediaEntity = await this.mediaRepository.createMedia({
                entityId: entity.id,
                modelMetadataId: mediaFieldMetadata.model.id,
                relativeUri: awsFileUrl,
                mimeType: file.mimetype,
                fileSize: file.size,
                originalFileName: file.originalname,
                mediaStorageProviderMetadataId: mediaFieldMetadata.mediaStorageProvider.id,
                fieldMetadataId: mediaFieldMetadata.id
            });
            result.push(mediaEntity);
            this.logger.debug(`Stored media with`, mediaEntity);
        }
        ;
        return result;
    }
    async delete(entity, mediaFieldMetadata) {
        const isSupportedEntity = entity instanceof common_entity_1.CommonEntity
            || entity instanceof legacy_common_entity_1.LegacyCommonEntity
            || entity instanceof legacy_common_with_id_entity_1.LegacyCommonWithIdEntity;
        if (!isSupportedEntity) {
            throw new Error("Entity must be an instance of CommonEntity, LegacyCommonEntity or LegacyCommonWithIdEntity");
        }
        const storageProvider = mediaFieldMetadata.mediaStorageProvider;
        const region = this.getEffectiveRegion(storageProvider.region);
        const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);
        this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id);
        for (const media of existingMedia) {
            const bucketName = storageProvider.bucketName;
            await this.s3FileService.delete(`${bucketName}:${media.relativeUri}`, { region });
        }
    }
    async deleteByMediaRecord(media) {
        const storageProvider = media?.mediaStorageProviderMetadata;
        if (!storageProvider) {
            throw new Error(`mediaStorageProviderMetadata is not populated for media id ${media?.id ?? 'unknown'}`);
        }
        if (!storageProvider?.bucketName || !media?.relativeUri) {
            return;
        }
        const region = this.getEffectiveRegion(storageProvider.region);
        await this.s3FileService.delete(`${storageProvider.bucketName}:${media.relativeUri}`, { region });
    }
    getEffectiveRegion(providerRegion) {
        return providerRegion || this.configService.get('S3_AWS_REGION_NAME');
    }
    getFullFilePath(media) {
        const region = this.getEffectiveRegion(media.mediaStorageProviderMetadata.region);
        return `https://${media.mediaStorageProviderMetadata.bucketName}.s3.${region}.amazonaws.com/${media.relativeUri}`;
    }
    getFileName(file) {
        return `${file.filename}-${file.originalname}`;
    }
};
exports.FileS3StorageProvider = FileS3StorageProvider;
exports.FileS3StorageProvider = FileS3StorageProvider = FileS3StorageProvider_1 = __decorate([
    (0, common_1.Injectable)(),
    __metadata("design:paramtypes", [config_1.ConfigService,
        file_1.DiskFileService,
        file_1.S3FileService,
        media_repository_1.MediaRepository])
], FileS3StorageProvider);
//# sourceMappingURL=file-s3-storage-provider.js.map