"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserAdminService = void 0;
const common_1 = require("@nestjs/common");
const constants_1 = require("../constants");
const asset_dto_1 = require("../dtos/asset.dto");
const session_dto_1 = require("../dtos/session.dto");
const user_preferences_dto_1 = require("../dtos/user-preferences.dto");
const user_dto_1 = require("../dtos/user.dto");
const enum_1 = require("../enum");
const base_service_1 = require("./base.service");
const user_methods_1 = require("./shared/user-methods");
const preferences_1 = require("../utils/preferences");
let UserAdminService = class UserAdminService extends base_service_1.BaseService {
    async search(auth, dto) {
        const users = await this.userRepository.getList({
            id: dto.id,
            withDeleted: dto.withDeleted,
        });
        return users.map((user) => (0, user_dto_1.mapUserAdmin)(user));
    }
    async create(dto) {
        const { notify, ...userDto } = dto;
        const config = await this.getConfig({ withCache: false });
        if (!config.oauth.enabled && !userDto.password) {
            throw new common_1.BadRequestException('password is required');
        }
        const user = await this.createUser(userDto);
        await this.eventRepository.emit('UserSignup', {
            notify: !!notify,
            id: user.id,
            password: userDto.password,
        });
        return (0, user_dto_1.mapUserAdmin)(user);
    }
    async get(auth, id) {
        const user = await this.findOrFail(id, { withDeleted: true });
        return (0, user_dto_1.mapUserAdmin)(user);
    }
    async update(auth, id, dto) {
        const user = await this.findOrFail(id, {});
        if (dto.isAdmin !== undefined && dto.isAdmin !== auth.user.isAdmin && auth.user.id === id) {
            throw new common_1.BadRequestException('Admin status can only be changed by another admin');
        }
        if (dto.quotaSizeInBytes && user.quotaSizeInBytes !== dto.quotaSizeInBytes) {
            await this.userRepository.syncUsage(id);
        }
        if (dto.email) {
            const duplicate = await this.userRepository.getByEmail(dto.email);
            if (duplicate && duplicate.id !== id) {
                this.logger.debug('Email already in use by another account');
                throw new common_1.BadRequestException('Email is not available');
            }
        }
        if (dto.storageLabel) {
            const duplicate = await this.userRepository.getByStorageLabel(dto.storageLabel);
            if (duplicate && duplicate.id !== id) {
                throw new common_1.BadRequestException('Storage label already in use by another account');
            }
        }
        if (dto.password) {
            dto.password = await this.cryptoRepository.hashBcrypt(dto.password, constants_1.SALT_ROUNDS);
        }
        if (dto.pinCode) {
            dto.pinCode = await this.cryptoRepository.hashBcrypt(dto.pinCode, constants_1.SALT_ROUNDS);
        }
        if (dto.storageLabel === '') {
            dto.storageLabel = null;
        }
        const updatedUser = await this.userRepository.update(id, { ...dto, updatedAt: new Date() });
        return (0, user_dto_1.mapUserAdmin)(updatedUser);
    }
    async delete(auth, id, dto) {
        const { force } = dto;
        await this.findOrFail(id, {});
        if (auth.user.id === id) {
            throw new common_1.ForbiddenException('Cannot delete your own account');
        }
        await this.albumRepository.softDeleteAll(id);
        const status = force ? enum_1.UserStatus.Removing : enum_1.UserStatus.Deleted;
        const user = await this.userRepository.update(id, { status, deletedAt: new Date() });
        await this.eventRepository.emit('UserTrash', user);
        if (force) {
            await this.jobRepository.queue({ name: enum_1.JobName.UserDelete, data: { id: user.id, force } });
        }
        return (0, user_dto_1.mapUserAdmin)(user);
    }
    async restore(auth, id) {
        await this.findOrFail(id, { withDeleted: true });
        await this.albumRepository.restoreAll(id);
        const user = await this.userRepository.restore(id);
        await this.eventRepository.emit('UserRestore', user);
        return (0, user_dto_1.mapUserAdmin)(user);
    }
    async getCalendarHeatmap(auth, id, dto) {
        await this.findOrFail(id, { withDeleted: false });
        return (0, user_methods_1.getCalendarHeatmap)(id, dto, { asset: this.assetRepository });
    }
    async getSessions(auth, id) {
        const sessions = await this.sessionRepository.getByUserId(id);
        return sessions.map((session) => (0, session_dto_1.mapSession)(session));
    }
    async getStatistics(auth, id, dto) {
        const stats = await this.assetRepository.getStatistics(id, dto);
        return (0, asset_dto_1.mapStats)(stats);
    }
    async getPreferences(auth, id) {
        await this.findOrFail(id, { withDeleted: true });
        const metadata = await this.userRepository.getMetadata(id);
        return (0, user_preferences_dto_1.mapPreferences)((0, preferences_1.getPreferences)(metadata));
    }
    async updatePreferences(auth, id, dto) {
        await this.findOrFail(id, { withDeleted: false });
        const metadata = await this.userRepository.getMetadata(id);
        const newPreferences = (0, preferences_1.mergePreferences)((0, preferences_1.getPreferences)(metadata), dto);
        await this.userRepository.upsertMetadata(id, {
            key: enum_1.UserMetadataKey.Preferences,
            value: (0, preferences_1.getPreferencesPartial)(newPreferences),
        });
        return (0, user_preferences_dto_1.mapPreferences)(newPreferences);
    }
    async findOrFail(id, options) {
        const user = await this.userRepository.get(id, options);
        if (!user) {
            throw new common_1.BadRequestException('User not found');
        }
        return user;
    }
};
exports.UserAdminService = UserAdminService;
exports.UserAdminService = UserAdminService = __decorate([
    (0, common_1.Injectable)()
], UserAdminService);
//# sourceMappingURL=user-admin.service.js.map