"use strict";
const api_types_1 = require("@n8n/api-types");
const db_1 = require("@n8n/db");
const data_table_repository_1 = require("../../../../modules/data-table/data-table.repository");
const di_1 = require("@n8n/di");
const global_middleware_1 = require("../../shared/middlewares/global.middleware");
const pagination_service_1 = require("../../shared/services/pagination.service");
const data_table_service_1 = require("../../../../modules/data-table/data-table.service");
const data_table_not_found_error_1 = require("../../../../modules/data-table/errors/data-table-not-found.error");
const data_table_name_conflict_error_1 = require("../../../../modules/data-table/errors/data-table-name-conflict.error");
const data_table_validation_error_1 = require("../../../../modules/data-table/errors/data-table-validation.error");
const handleError = (error, res) => {
    if (error instanceof data_table_not_found_error_1.DataTableNotFoundError) {
        return res.status(404).json({ message: error.message });
    }
    if (error instanceof data_table_name_conflict_error_1.DataTableNameConflictError) {
        return res.status(409).json({ message: error.message });
    }
    if (error instanceof data_table_validation_error_1.DataTableValidationError) {
        return res.status(400).json({ message: error.message });
    }
    if (error instanceof Error) {
        return res.status(400).json({ message: error.message });
    }
    throw error;
};
const stringifyQuery = (query) => {
    const result = {};
    for (const [key, value] of Object.entries(query)) {
        if (value !== undefined && value !== null) {
            result[key] = String(value);
        }
    }
    return result;
};
const getProjectIdForDataTable = async (dataTableId) => {
    const dataTable = await di_1.Container.get(data_table_repository_1.DataTableRepository).findOne({
        where: { id: dataTableId },
        relations: ['project'],
    });
    if (!dataTable) {
        throw new data_table_not_found_error_1.DataTableNotFoundError(dataTableId);
    }
    return dataTable.project.id;
};
module.exports = {
    listDataTables: [
        (0, global_middleware_1.publicApiScope)('dataTable:list'),
        global_middleware_1.validCursor,
        async (req, res) => {
            try {
                const payload = api_types_1.PublicApiListDataTableQueryDto.safeParse(stringifyQuery(req.query));
                if (!payload.success) {
                    return res.status(400).json({
                        message: payload.error.errors[0]?.message || 'Invalid query parameters',
                    });
                }
                const { offset, limit, filter, sortBy } = payload.data;
                const providedFilter = filter ?? {};
                const { projectId: _ignoredProjectId, ...restFilter } = providedFilter;
                const isGlobalOwnerOrAdmin = ['global:owner', 'global:admin'].includes(req.user.role.slug);
                let finalFilter;
                if (isGlobalOwnerOrAdmin) {
                    finalFilter = restFilter;
                }
                else {
                    const personalProject = await di_1.Container.get(db_1.ProjectRepository).getPersonalProjectForUserOrFail(req.user.id);
                    const projectRelations = await di_1.Container.get(db_1.ProjectRelationRepository).find({
                        where: { userId: req.user.id },
                        relations: ['project'],
                    });
                    const teamProjectIds = projectRelations
                        .filter((rel) => rel.project.type === 'team')
                        .map((rel) => rel.projectId);
                    const allAccessibleProjectIds = [personalProject.id, ...teamProjectIds];
                    finalFilter = {
                        ...restFilter,
                        projectId: allAccessibleProjectIds,
                    };
                }
                const result = await di_1.Container.get(data_table_service_1.DataTableService).getManyAndCount({
                    skip: offset,
                    take: limit,
                    filter: finalFilter,
                    sortBy,
                });
                const data = result.data.map(({ project: _project, ...rest }) => rest);
                return res.json({
                    data,
                    nextCursor: (0, pagination_service_1.encodeNextCursor)({
                        offset,
                        limit,
                        numberOfTotalRecords: result.count,
                    }),
                });
            }
            catch (error) {
                return handleError(error, res);
            }
        },
    ],
    createDataTable: [
        (0, global_middleware_1.publicApiScope)('dataTable:create'),
        async (req, res) => {
            try {
                const payload = api_types_1.CreateDataTableDto.safeParse(req.body);
                if (!payload.success) {
                    return res.status(400).json({
                        message: payload.error.errors[0]?.message || 'Invalid request body',
                    });
                }
                const project = await di_1.Container.get(db_1.ProjectRepository).getPersonalProjectForUserOrFail(req.user.id);
                const result = await di_1.Container.get(data_table_service_1.DataTableService).createDataTable(project.id, payload.data);
                const { project: _project, ...dataTable } = result;
                return res.status(201).json(dataTable);
            }
            catch (error) {
                return handleError(error, res);
            }
        },
    ],
    getDataTable: [
        (0, global_middleware_1.publicApiScope)('dataTable:read'),
        (0, global_middleware_1.projectScope)('dataTable:read', 'dataTable'),
        async (req, res) => {
            try {
                const { dataTableId } = req.params;
                const projectId = await getProjectIdForDataTable(dataTableId);
                const result = await di_1.Container.get(data_table_repository_1.DataTableRepository).findOne({
                    where: { id: dataTableId, project: { id: projectId } },
                    relations: ['project', 'columns'],
                });
                if (!result) {
                    throw new data_table_not_found_error_1.DataTableNotFoundError(dataTableId);
                }
                const { project: _project, ...dataTable } = result;
                return res.json(dataTable);
            }
            catch (error) {
                return handleError(error, res);
            }
        },
    ],
    updateDataTable: [
        (0, global_middleware_1.publicApiScope)('dataTable:update'),
        (0, global_middleware_1.projectScope)('dataTable:update', 'dataTable'),
        async (req, res) => {
            try {
                const { dataTableId } = req.params;
                const payload = api_types_1.UpdateDataTableDto.safeParse(req.body);
                if (!payload.success) {
                    return res.status(400).json({
                        message: payload.error.errors[0]?.message || 'Invalid request body',
                    });
                }
                const projectId = await getProjectIdForDataTable(dataTableId);
                await di_1.Container.get(data_table_service_1.DataTableService).updateDataTable(dataTableId, projectId, payload.data);
                const result = await di_1.Container.get(data_table_repository_1.DataTableRepository).findOne({
                    where: { id: dataTableId, project: { id: projectId } },
                    relations: ['project', 'columns'],
                });
                if (!result) {
                    throw new data_table_not_found_error_1.DataTableNotFoundError(dataTableId);
                }
                const { project: _project, ...dataTable } = result;
                return res.json(dataTable);
            }
            catch (error) {
                return handleError(error, res);
            }
        },
    ],
    deleteDataTable: [
        (0, global_middleware_1.publicApiScope)('dataTable:delete'),
        (0, global_middleware_1.projectScope)('dataTable:delete', 'dataTable'),
        async (req, res) => {
            try {
                const { dataTableId } = req.params;
                const projectId = await getProjectIdForDataTable(dataTableId);
                await di_1.Container.get(data_table_service_1.DataTableService).deleteDataTable(dataTableId, projectId);
                return res.status(204).send();
            }
            catch (error) {
                return handleError(error, res);
            }
        },
    ],
};
//# sourceMappingURL=data-tables.handler.js.map