"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);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FavoritesService = void 0;
const di_1 = require("@n8n/di");
const db_1 = require("@n8n/db");
const typeorm_1 = require("@n8n/typeorm");
const user_favorite_repository_1 = require("./database/repositories/user-favorite.repository");
const bad_request_error_1 = require("../../errors/response-errors/bad-request.error");
const not_found_error_1 = require("../../errors/response-errors/not-found.error");
const data_table_repository_1 = require("../../modules/data-table/data-table.repository");
let FavoritesService = class FavoritesService {
    constructor(userFavoriteRepository, workflowRepository, projectRepository, sharedWorkflowRepository, dataTableRepository, folderRepository) {
        this.userFavoriteRepository = userFavoriteRepository;
        this.workflowRepository = workflowRepository;
        this.projectRepository = projectRepository;
        this.sharedWorkflowRepository = sharedWorkflowRepository;
        this.dataTableRepository = dataTableRepository;
        this.folderRepository = folderRepository;
        this.MAX_FAVORITES = 200;
    }
    async getEnrichedFavorites(userId) {
        const favorites = await this.userFavoriteRepository.findByUser(userId);
        if (favorites.length === 0)
            return [];
        const workflowIds = favorites
            .filter((f) => f.resourceType === 'workflow')
            .map((f) => f.resourceId);
        const dataTableIds = favorites
            .filter((f) => f.resourceType === 'dataTable')
            .map((f) => f.resourceId);
        const folderIds = favorites.filter((f) => f.resourceType === 'folder').map((f) => f.resourceId);
        const accessibleProjects = await this.projectRepository.getAccessibleProjects(userId);
        const accessibleProjectIds = new Set(accessibleProjects.map((p) => p.id));
        const projectNameMap = new Map(accessibleProjects.map((p) => [p.id, p.name ?? '']));
        const [workflows, sharedWorkflows, dataTables, folders] = await Promise.all([
            workflowIds.length > 0 && accessibleProjectIds.size > 0
                ? this.workflowRepository.findByIds(workflowIds, { fields: ['id', 'name'] })
                : [],
            workflowIds.length > 0 && accessibleProjectIds.size > 0
                ? this.sharedWorkflowRepository.find({
                    select: { workflowId: true },
                    where: { workflowId: (0, typeorm_1.In)(workflowIds), projectId: (0, typeorm_1.In)([...accessibleProjectIds]) },
                })
                : [],
            dataTableIds.length > 0
                ? this.dataTableRepository.find({ where: { id: (0, typeorm_1.In)(dataTableIds) } })
                : [],
            folderIds.length > 0
                ? this.folderRepository.find({
                    where: { id: (0, typeorm_1.In)(folderIds) },
                    relations: { homeProject: true },
                })
                : [],
        ]);
        const workflowNameMap = new Map();
        if (workflowIds.length > 0 && accessibleProjectIds.size > 0) {
            const wfMap = new Map(workflows.map((wf) => [wf.id, wf.name]));
            const accessibleWfIds = new Set(sharedWorkflows.map((sw) => sw.workflowId));
            for (const id of workflowIds) {
                const name = wfMap.get(id);
                if (accessibleWfIds.has(id) && name !== undefined) {
                    workflowNameMap.set(id, name);
                }
            }
        }
        const dataTableMetaMap = new Map();
        for (const dt of dataTables) {
            if (accessibleProjectIds.has(dt.projectId)) {
                dataTableMetaMap.set(dt.id, { name: dt.name, projectId: dt.projectId });
            }
        }
        const folderMetaMap = new Map();
        for (const folder of folders) {
            const projectId = folder.homeProject?.id;
            if (projectId && accessibleProjectIds.has(projectId)) {
                folderMetaMap.set(folder.id, { name: folder.name, projectId });
            }
        }
        const enriched = [];
        for (const fav of favorites) {
            if (fav.resourceType === 'workflow') {
                const name = workflowNameMap.get(fav.resourceId);
                if (name !== undefined)
                    enriched.push({ ...fav, resourceName: name });
            }
            else if (fav.resourceType === 'project') {
                const name = projectNameMap.get(fav.resourceId);
                if (name !== undefined) {
                    enriched.push({ ...fav, resourceName: name });
                }
            }
            else if (fav.resourceType === 'dataTable') {
                const meta = dataTableMetaMap.get(fav.resourceId);
                if (meta !== undefined) {
                    enriched.push({ ...fav, resourceName: meta.name, resourceProjectId: meta.projectId });
                }
            }
            else if (fav.resourceType === 'folder') {
                const meta = folderMetaMap.get(fav.resourceId);
                if (meta !== undefined) {
                    enriched.push({ ...fav, resourceName: meta.name, resourceProjectId: meta.projectId });
                }
            }
        }
        return enriched;
    }
    async addFavorite(userId, resourceId, resourceType) {
        const existing = await this.userFavoriteRepository.findOne({
            where: { userId, resourceId, resourceType },
        });
        if (existing)
            return existing;
        await this.assertResourceExists(resourceId, resourceType);
        const count = await this.userFavoriteRepository.count({ where: { userId } });
        if (count >= this.MAX_FAVORITES) {
            throw new bad_request_error_1.BadRequestError(`Favorites limit of ${this.MAX_FAVORITES} reached`);
        }
        const favorite = this.userFavoriteRepository.create({ userId, resourceId, resourceType });
        return await this.userFavoriteRepository.save(favorite);
    }
    async assertResourceExists(resourceId, resourceType) {
        let exists;
        switch (resourceType) {
            case 'workflow':
                exists = await this.workflowRepository.existsBy({ id: resourceId });
                break;
            case 'project':
                exists = await this.projectRepository.existsBy({ id: resourceId });
                break;
            case 'dataTable':
                exists = await this.dataTableRepository.existsBy({ id: resourceId });
                break;
            case 'folder':
                exists = await this.folderRepository.existsBy({ id: resourceId });
                break;
        }
        if (!exists) {
            throw new not_found_error_1.NotFoundError(`${resourceType} with id "${resourceId}" not found`);
        }
    }
    async removeFavorite(userId, resourceId, resourceType) {
        const favorite = await this.userFavoriteRepository.findOne({
            where: { userId, resourceId, resourceType },
        });
        if (!favorite) {
            throw new not_found_error_1.NotFoundError('Favorite not found');
        }
        await this.userFavoriteRepository.remove(favorite);
    }
    async deleteByResource(resourceId, resourceType) {
        await this.userFavoriteRepository.deleteByResourceId(resourceId, resourceType);
    }
    async deleteByResourceIds(resourceIds, resourceType) {
        await this.userFavoriteRepository.deleteByResourceIds(resourceIds, resourceType);
    }
};
exports.FavoritesService = FavoritesService;
exports.FavoritesService = FavoritesService = __decorate([
    (0, di_1.Service)(),
    __metadata("design:paramtypes", [user_favorite_repository_1.UserFavoriteRepository,
        db_1.WorkflowRepository,
        db_1.ProjectRepository,
        db_1.SharedWorkflowRepository,
        data_table_repository_1.DataTableRepository,
        db_1.FolderRepository])
], FavoritesService);
//# sourceMappingURL=favorites.service.js.map