"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchRedteamResultList = void 0;
const drizzle_orm_1 = require("drizzle-orm");
const constants_1 = require("../../../constants");
const get_upgrade_meta_1 = require("../../../util/get-upgrade-meta");
const time_1 = require("../../../util/time");
const decimal_js_1 = __importDefault(require("decimal.js"));
const restriction_message_1 = require("../../constants/restriction.message");
const tables_1 = require("../../../database/tables");
const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
const parseCommaUuidList = (raw) => {
    const parts = [];
    const pushSplit = (value) => {
        if (typeof value !== 'string') {
            return;
        }
        for (const piece of value.split(',')) {
            const t = piece.trim();
            if (t) {
                parts.push(t);
            }
        }
    };
    if (Array.isArray(raw)) {
        for (const entry of raw) {
            pushSplit(entry);
        }
    }
    else {
        pushSplit(raw);
    }
    return [...new Set(parts.filter((p) => UUID_V4_RE.test(p)))];
};
const fetchRedteamResultList = async (params) => {
    const { db, orgId, projectId, limit = 10, offset = 0 } = params;
    const applicationIdsFilter = parseCommaUuidList(params.applicationIds);
    const securityConfigIdsFilter = parseCommaUuidList(params.securityConfigIds);
    const baseWhere = (0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.testRunsTable.projectId, projectId), (0, drizzle_orm_1.eq)(tables_1.testRunsTable.type, constants_1.TEST_RUN_TYPE.SECURITY));
    /** When both filters are set, runs matching either filter are included (OR). */
    const filterParts = [];
    if (applicationIdsFilter.length > 0) {
        const overlapConditions = applicationIdsFilter.map((id) => (0, drizzle_orm_1.sql) `${tables_1.testRunsTable.applicationIds}::jsonb @> ${drizzle_orm_1.sql.raw(`'${JSON.stringify([id])}'::jsonb`)}`);
        filterParts.push(overlapConditions.length === 1 ? overlapConditions[0] : (0, drizzle_orm_1.or)(...overlapConditions));
    }
    if (securityConfigIdsFilter.length > 0) {
        const idsIn = drizzle_orm_1.sql.join(securityConfigIdsFilter.map((id) => (0, drizzle_orm_1.sql) `${id}`), (0, drizzle_orm_1.sql) `, `);
        filterParts.push((0, drizzle_orm_1.sql) `EXISTS (
      SELECT 1 FROM test_runs_to_security_configs trsc
      WHERE trsc.test_run_id = ${tables_1.testRunsTable.id}
      AND trsc.security_config_id IN (${idsIn})
    )`);
    }
    const listWhere = filterParts.length === 0
        ? baseWhere
        : filterParts.length === 1
            ? (0, drizzle_orm_1.and)(baseWhere, filterParts[0])
            : (0, drizzle_orm_1.and)(baseWhere, (0, drizzle_orm_1.or)(...filterParts));
    // Get total count for pagination
    const totalCount = await db
        .select({ count: (0, drizzle_orm_1.sql) `count(*)` })
        .from(tables_1.testRunsTable)
        .where(listWhere)
        .then((result) => Number(result[0].count));
    const results = await db
        .select({
        id: tables_1.testRunsTable.id,
        type: tables_1.testRunsTable.type,
        status: tables_1.testRunsTable.status,
        createdAt: tables_1.testRunsTable.createdAt,
        projectId: tables_1.testRunsTable.projectId,
        applicationIds: tables_1.testRunsTable.applicationIds,
        libraryId: tables_1.testRunsTable.libraryId,
        evalId: tables_1.testRunsToEvalsTable.evalId,
        redteamConfig: tables_1.evalsTable.config,
        // Add security config fields
        securityConfigId: tables_1.testRunsToSecurityConfigsTable.securityConfigId,
        securityConfigName: tables_1.securityConfigTable?.name,
        securityConfig: tables_1.securityConfigTable.config,
    })
        .from(tables_1.testRunsTable)
        .leftJoin(tables_1.testRunsToEvalsTable, (0, drizzle_orm_1.sql) `${tables_1.testRunsTable.id} = ${tables_1.testRunsToEvalsTable.testRunId}`)
        .leftJoin(tables_1.evalsTable, (0, drizzle_orm_1.sql) `${tables_1.testRunsToEvalsTable.evalId} = ${tables_1.evalsTable.id}`)
        .leftJoin(tables_1.testRunsToSecurityConfigsTable, (0, drizzle_orm_1.sql) `${tables_1.testRunsTable.id} = ${tables_1.testRunsToSecurityConfigsTable.testRunId}`)
        .leftJoin(tables_1.securityConfigTable, (0, drizzle_orm_1.sql) `${tables_1.testRunsToSecurityConfigsTable.securityConfigId} = ${tables_1.securityConfigTable.id}`)
        .where(listWhere)
        .limit(limit)
        .offset(offset)
        .orderBy((0, drizzle_orm_1.desc)(tables_1.testRunsTable.createdAt));
    // Get application names
    const applicationIds = results.flatMap((r) => r.applicationIds || []);
    const applications = await db
        .select({
        id: tables_1.applicationsTable.id,
        name: tables_1.applicationsTable.name,
    })
        .from(tables_1.applicationsTable)
        .where((0, drizzle_orm_1.inArray)(tables_1.applicationsTable.id, applicationIds));
    const appMap = new Map(applications.map((app) => [app.id, app.name]));
    // Process results to include application names and redteam stats
    const processedResults = results.map((result) => ({
        id: result?.id,
        evalId: result?.evalId,
        createdAt: result?.createdAt,
        status: result?.status,
        securityConfigName: result?.securityConfigName,
        applications: (result?.applicationIds || []).map((id) => appMap.get(id) || id),
        redteamStats: result?.status === constants_1.TEST_RUN_STATUS.COMPLETED
            ? {
                strategiesCount: result?.redteamConfig?.redteam?.strategies?.length || 0,
                pluginsCount: result?.redteamConfig?.redteam?.plugins?.length || 0,
            }
            : {
                strategiesCount: result?.redteamConfig?.redteam?.strategies?.length || result?.securityConfig?.strategies?.length || 0,
                pluginsCount: result?.redteamConfig?.redteam?.plugins?.length || result?.securityConfig?.plugins?.length || 0,
            },
        // Add security config info
        securityConfigId: result.securityConfigId,
    }));
    const { upgradeMetadata, isEnterprise, restrictionsData, globalBanner, wallet, isStarter, thresholds, usages, } = await (0, get_upgrade_meta_1.getUpgradeMetaByOrgId)(orgId, {
        fetchMetricUsage: true,
    });
    if (!isEnterprise && restrictionsData?.security_evals > 0) {
        const whereConditions = (0, time_1.createTimespanWhereConditions)({
            table: tables_1.testRunsTable,
            timeColumn: 'createdAt',
            orgId: orgId,
            timespan: restrictionsData?.security_evals_timespan || 'lifetime',
            extraConditions: (0, drizzle_orm_1.and)((0, drizzle_orm_1.sql) `${tables_1.testRunsTable.type} = ${constants_1.TEST_RUN_TYPE.SECURITY}`, (0, drizzle_orm_1.sql) `${tables_1.testRunsTable.status} = ${constants_1.TEST_RUN_STATUS.COMPLETED}`),
        });
        const count = await db
            .select({ count: (0, drizzle_orm_1.sql) `count(*)` })
            .from(tables_1.testRunsTable)
            .where(whereConditions)
            .then((result) => Number(result[0]?.count));
        if (count != 0
            && new decimal_js_1.default(count).gte(restrictionsData?.security_evals ?? 0)) {
            upgradeMetadata.upgradeRequired = true;
            upgradeMetadata.topUpRequired = false;
            upgradeMetadata.upgradeTitle = restriction_message_1.RESTRICTION_MESSAGE.upgrade.title;
            upgradeMetadata.upgradeMessage = restriction_message_1.RESTRICTION_MESSAGE.upgrade.message;
            upgradeMetadata.currentPlan = restrictionsData?.currentPlan ?? '';
            upgradeMetadata.currentPlanId = restrictionsData?.currentPlanId ?? '';
            globalBanner.show = true;
            globalBanner.data.content = `You're out of allotted security evaluation runs with your ${restrictionsData?.currentPlan ?? ''} plan. `;
            globalBanner.data.type = 'upgrade';
            globalBanner.data.action = 'Upgrade Now';
            globalBanner.data.actionType = 'upgrade';
            globalBanner.data.actionContent = `to create more security evals`;
        }
    }
    if (!isEnterprise) {
        const isLowOnBalance = new decimal_js_1.default(wallet?.credits ?? 0).lte(new decimal_js_1.default(thresholds?.walletNotificationThreshold ?? 0));
        if (isLowOnBalance) {
            globalBanner.show = true;
            globalBanner.data.content = `You're low on TRU CREDITS`;
            globalBanner.data.type = 'credits';
            globalBanner.data.action = 'Add TRU CREDITS';
            globalBanner.data.actionType = 'credits';
            globalBanner.data.actionContent = `to continue evaluating your application`;
        }
    }
    if (!isEnterprise && new decimal_js_1.default(wallet?.credits ?? 0).lte(0)) {
        globalBanner.show = true;
        globalBanner.data.content = `You're low on TRU CREDITS`;
        globalBanner.data.type = 'credits';
        globalBanner.data.action = 'Add TRU CREDITS';
        globalBanner.data.actionType = 'credits';
        globalBanner.data.actionContent = `to continue evaluating your application`;
        upgradeMetadata.topUpRequired = true;
        upgradeMetadata.upgradeRequired = false;
        upgradeMetadata.upgradeTitle = restriction_message_1.RESTRICTION_MESSAGE.lowCredits.title;
        upgradeMetadata.upgradeMessage = restriction_message_1.RESTRICTION_MESSAGE.lowCredits.message;
        upgradeMetadata.currentPlan = restrictionsData?.currentPlan ?? '';
        upgradeMetadata.currentPlanId = restrictionsData?.currentPlanId ?? '';
    }
    if (isStarter
        && new decimal_js_1.default(usages?.metric ?? 0).gt(0)
        && new decimal_js_1.default(usages?.metric ?? 0).gte(restrictionsData?.metrics ?? 0)) {
        globalBanner.show = true;
        globalBanner.data.content = `You're out of allotted metrics with your ${restrictionsData?.currentPlan ?? ''} plan. `;
        globalBanner.data.type = 'upgrade';
        globalBanner.data.action = 'Upgrade Now';
        globalBanner.data.actionType = 'upgrade';
        globalBanner.data.actionContent = `to continue evaluating your application`;
        upgradeMetadata.upgradeRequired = true;
        upgradeMetadata.topUpRequired = false;
        upgradeMetadata.upgradeTitle = restriction_message_1.RESTRICTION_MESSAGE.metrics.title;
        upgradeMetadata.upgradeMessage = restriction_message_1.RESTRICTION_MESSAGE.metrics.message;
        upgradeMetadata.currentPlan = restrictionsData?.currentPlan ?? '';
        upgradeMetadata.currentPlanId = restrictionsData?.currentPlanId ?? '';
    }
    return {
        data: processedResults,
        pagination: {
            total: totalCount,
            page: Math.floor(offset / limit) + 1,
            limit,
            totalPages: Math.ceil(totalCount / limit),
        },
        upgradeMetadata,
        globalBanner,
    };
};
exports.fetchRedteamResultList = fetchRedteamResultList;
//# sourceMappingURL=get-redteam-result-list.js.map