"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 __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MenuItemMetadataService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const core_1 = require("@nestjs/core");
const typeorm_2 = require("typeorm");
const crud_service_1 = require("./crud.service");
const lodash_1 = require("lodash");
const menu_item_metadata_repository_1 = require("../repository/menu-item-metadata.repository");
const saved_filters_repository_1 = require("../repository/saved-filters.repository");
let MenuItemMetadataService = class MenuItemMetadataService extends crud_service_1.CRUDService {
    constructor(entityManager, repo, savedFiltersRepo, moduleRef) {
        super(entityManager, repo, 'menuItemMetadata', 'solid-core', moduleRef);
        this.entityManager = entityManager;
        this.repo = repo;
        this.savedFiltersRepo = savedFiltersRepo;
        this.moduleRef = moduleRef;
    }
    async findOneByUserKey(name, relations = {}) {
        const entity = await this.repo.findOne({
            where: {
                name: name,
            },
            relations: relations,
        });
        return entity;
    }
    async upsert(updateSolidMenuItemDto) {
        const { moduleUserKey, parentMenuItemUserKey, actionUserKey, rolesIds, rolesCommand, ...cleanUpdateSolidMenuItemDto } = updateSolidMenuItemDto;
        const existingMenuItem = await this.repo.findOne({
            where: {
                name: updateSolidMenuItemDto.name
            },
            relations: ["roles"]
        });
        if (existingMenuItem) {
        }
        else {
            const moduleMetadata = this.repo.create(cleanUpdateSolidMenuItemDto);
            return this.repo.save(moduleMetadata);
        }
    }
    async findUserMenus(activeUser) {
        const qb = await this.repo.createSecurityRuleAwareQueryBuilder('menuItem');
        const menuItems = await qb
            .leftJoinAndSelect('menuItem.module', 'module')
            .leftJoinAndSelect('menuItem.parentMenuItem', 'parentMenuItem')
            .leftJoinAndSelect('menuItem.action', 'action')
            .leftJoinAndSelect('action.model', 'model')
            .leftJoinAndSelect('action.view', 'view')
            .leftJoinAndSelect('menuItem.roles', 'roles')
            .where('roles.name IN (:...roleNames)', { roleNames: activeUser.roles })
            .addOrderBy('module.menuSequenceNumber', 'ASC')
            .addOrderBy('menuItem.sequenceNumber', 'ASC')
            .getMany();
        const modulesToMenuItemsMap = new Map();
        const modulesMap = new Map();
        menuItems.forEach(menuItem => {
            const moduleName = menuItem.module.name;
            if (!modulesToMenuItemsMap.has(moduleName)) {
                modulesToMenuItemsMap.set(moduleName, []);
            }
            modulesToMenuItemsMap.get(moduleName).push(menuItem);
            if (!modulesMap.has(moduleName)) {
                modulesMap.set(moduleName, menuItem.module);
            }
        });
        const menu = [];
        for (const [moduleName, menuItemsForModule] of modulesToMenuItemsMap.entries()) {
            const rootMenuItems = menuItemsForModule.filter(item => !item.parentMenuItem);
            const moduleMetadata = modulesMap.get(moduleName);
            const moduleMenu = {
                title: moduleMetadata.displayName,
                key: moduleName.toLowerCase().replace(/\s+/g, '-'),
                children: await this.buildMenuTree(rootMenuItems, menuItemsForModule, activeUser),
                icon: moduleMetadata.menuIconUrl,
            };
            menu.push(moduleMenu);
        }
        return menu.filter(m => m.children.length > 0);
    }
    async buildMenuTree(rootItems, allMenuItems, activeUser) {
        const menuItemsData = await Promise.all(rootItems.map(async (rootItem) => {
            const allowedMenuItems = allMenuItems.filter(i => {
                if (!i.parentMenuItem) {
                    return true;
                }
                else {
                    if (i.action.type === 'custom') {
                        return true;
                    }
                    return this.crudHelperService.hasReadPermissionOnModel(activeUser, i.action.model.singularName);
                }
            });
            const children = allowedMenuItems.filter(item => item.parentMenuItem && item.parentMenuItem.id === rootItem.id);
            const menuItemId = rootItem?.id ?? "";
            const menuItemName = rootItem?.name ?? "";
            const actionId = rootItem?.action?.id ?? "";
            const actionName = rootItem?.action?.name ?? "";
            let path = '';
            const layout = rootItem?.action?.view && rootItem?.action?.view?.layout ? JSON.parse(rootItem?.action?.view?.layout) : null;
            let savedFilterId = null;
            if (layout && layout?.attrs?.defaultSavedFilter) {
                const savedFilter = await this.savedFiltersRepo.findOne({
                    where: {
                        name: layout?.attrs?.defaultSavedFilter,
                        isPrivate: false
                    },
                });
                if (savedFilter) {
                    savedFilterId = savedFilter.id;
                }
            }
            if (rootItem.action && rootItem.action.type === 'custom') {
                path = `${rootItem.action.customComponent}?menuItemId=${menuItemId}&menuItemName=${menuItemName}&actionId=${actionId}&actionName=${actionName}${savedFilterId ? `&savedQuery=${savedFilterId}` : ''}`;
            }
            if (rootItem.action && rootItem.action.type === 'solid') {
                if (this.crudHelperService.hasReadPermissionOnModel(activeUser, rootItem.action.model.singularName)) {
                    path = `/admin/core/${rootItem.module.name}/${(0, lodash_1.kebabCase)(rootItem.action?.model?.singularName ?? 'unknown')}/${rootItem.action?.view?.type ?? 'list'}?menuItemId=${menuItemId}&menuItemName=${menuItemName}&actionId=${actionId}&actionName=${actionName}${savedFilterId ? `&savedQuery=${savedFilterId}` : ''}`;
                }
            }
            const data = {
                title: rootItem.displayName || rootItem.name,
                path: path,
                key: rootItem.name.toLowerCase().replace(/\s+/g, '-'),
                icon: rootItem.iconName,
            };
            if (children.length > 0) {
                data["children"] = await this.buildMenuTree(children, allMenuItems, activeUser);
            }
            return data;
        }));
        return menuItemsData.filter(mi => mi && mi);
    }
};
exports.MenuItemMetadataService = MenuItemMetadataService;
exports.MenuItemMetadataService = MenuItemMetadataService = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, typeorm_1.InjectEntityManager)()),
    __metadata("design:paramtypes", [typeorm_2.EntityManager,
        menu_item_metadata_repository_1.MenuItemMetadataRepository,
        saved_filters_repository_1.SavedFiltersRepository,
        core_1.ModuleRef])
], MenuItemMetadataService);
//# sourceMappingURL=menu-item-metadata.service.js.map