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);
};
import DatabaseService from "./DatabaseService";
import Model from "../../Models/DatabaseModels/TelemetryException";
import AIAgentTask from "../../Models/DatabaseModels/AIAgentTask";
import ObjectID from "../../Types/ObjectID";
import SortOrder from "../../Types/BaseDatabase/SortOrder";
import BadDataException from "../../Types/Exception/BadDataException";
import AIAgentTaskType from "../../Types/AI/AIAgentTaskType";
import AIAgentTaskStatus from "../../Types/AI/AIAgentTaskStatus";
import AIAgentTaskService from "./AIAgentTaskService";
import AIAgentTaskTelemetryExceptionService from "./AIAgentTaskTelemetryExceptionService";
import QueryHelper from "../Types/Database/QueryHelper";
import ModelPermission from "../Types/Database/Permissions/Index";
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
export class Service extends DatabaseService {
    constructor() {
        super(Model);
    }
    async createAIAgentTaskForException(params) {
        const { telemetryExceptionId, props } = params;
        // Get the telemetry exception
        const telemetryException = await this.findOneById({
            id: telemetryExceptionId,
            select: {
                _id: true,
                projectId: true,
                message: true,
                stackTrace: true,
                primaryEntityId: true,
                exceptionType: true,
            },
            props,
        });
        if (!telemetryException || !telemetryException.projectId) {
            throw new BadDataException("Telemetry Exception not found");
        }
        // Check if an active AI agent task already exists for this exception
        await this.validateNoActiveTaskExists(telemetryExceptionId);
        // Create the AI Agent Task
        const createdTask = await this.createFixExceptionTask({
            telemetryException,
            telemetryExceptionId,
            props,
        });
        // Link the task to the telemetry exception
        await AIAgentTaskTelemetryExceptionService.linkTaskToTelemetryException({
            projectId: telemetryException.projectId,
            aiAgentTaskId: createdTask.id,
            telemetryExceptionId,
            props,
        });
        return createdTask;
    }
    async validateNoActiveTaskExists(telemetryExceptionId) {
        const existingTaskLink = await AIAgentTaskTelemetryExceptionService.findOneBy({
            query: {
                telemetryExceptionId: telemetryExceptionId,
                aiAgentTask: {
                    status: QueryHelper.notIn([
                        AIAgentTaskStatus.Completed,
                        AIAgentTaskStatus.Error,
                    ]),
                },
            },
            select: {
                _id: true,
                aiAgentTaskId: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (existingTaskLink) {
            throw new BadDataException("An AI agent task is already in progress for this exception. Please wait for it to complete before creating a new one.");
        }
    }
    async createFixExceptionTask(params) {
        const { telemetryException, telemetryExceptionId, props } = params;
        const aiAgentTask = new AIAgentTask();
        aiAgentTask.projectId = telemetryException.projectId;
        aiAgentTask.taskType = AIAgentTaskType.FixException;
        aiAgentTask.status = AIAgentTaskStatus.Scheduled;
        // Set name and description based on exception details
        const exceptionType = telemetryException.exceptionType || "Exception";
        const exceptionMessage = telemetryException.message || "No message available";
        aiAgentTask.name = `Fix ${exceptionType}: ${exceptionMessage}`;
        aiAgentTask.description = `AI Agent task to fix the exception: ${exceptionMessage}`;
        // Build metadata
        aiAgentTask.metadata = this.buildFixExceptionMetadata({
            telemetryException,
            telemetryExceptionId,
        });
        const createdTask = await AIAgentTaskService.create({
            data: aiAgentTask,
            props: Object.assign({}, props),
        });
        if (!createdTask.id) {
            throw new BadDataException("Failed to create AI Agent Task");
        }
        return createdTask;
    }
    async getDashboardSummary(props) {
        if (!props.tenantId) {
            throw new BadDataException("Project ID is required");
        }
        const projectId = props.tenantId;
        const exceptionSelect = {
            _id: true,
            message: true,
            exceptionType: true,
            fingerprint: true,
            isResolved: true,
            isArchived: true,
            occuranceCount: true,
            lastSeenAt: true,
            firstSeenAt: true,
            environment: true,
            // primaryEntityId is polymorphic; the client resolves it per primaryEntityType.
            primaryEntityId: true,
            primaryEntityType: true,
        };
        const [unresolvedCount, resolvedCount, archivedCount, topExceptions, recentExceptions, serviceSummaries,] = await Promise.all([
            this.countBy({
                query: {
                    projectId,
                    isResolved: false,
                    isArchived: false,
                },
                props,
            }),
            this.countBy({
                query: {
                    projectId,
                    isResolved: true,
                    isArchived: false,
                },
                props,
            }),
            this.countBy({
                query: {
                    projectId,
                    isArchived: true,
                },
                props,
            }),
            this.findBy({
                query: {
                    projectId,
                    isResolved: false,
                    isArchived: false,
                },
                select: exceptionSelect,
                limit: 10,
                skip: 0,
                sort: {
                    occuranceCount: SortOrder.Descending,
                },
                props,
            }),
            this.findBy({
                query: {
                    projectId,
                    isResolved: false,
                    isArchived: false,
                },
                select: exceptionSelect,
                limit: 5,
                skip: 0,
                sort: {
                    lastSeenAt: SortOrder.Descending,
                },
                props,
            }),
            this.aggregateUnresolvedByService(projectId, props),
        ]);
        return {
            unresolvedCount: unresolvedCount.toNumber(),
            resolvedCount: resolvedCount.toNumber(),
            archivedCount: archivedCount.toNumber(),
            topExceptions,
            recentExceptions,
            serviceSummaries,
        };
    }
    async aggregateUnresolvedByService(projectId, props) {
        var _a;
        /*
         * Assert the caller has read permission on TelemetryException. We don't
         * use the returned filtered query — we run a raw GROUP BY below for
         * efficiency — but this throws if the user lacks read access.
         */
        await ModelPermission.checkReadQueryPermission(Model, {
            projectId,
            isResolved: false,
            isArchived: false,
        }, null, props);
        const rows = (await this.getQueryBuilder("TelemetryException")
            .select(`"TelemetryException"."primaryEntityId"`, "primaryEntityId")
            .addSelect(`"TelemetryException"."primaryEntityType"`, "primaryEntityType")
            .addSelect(`COUNT(*)`, "unresolvedCount")
            .addSelect(`COALESCE(SUM("TelemetryException"."occuranceCount"), 0)`, "totalOccurrences")
            .where(`"TelemetryException"."projectId" = :projectId`, {
            projectId: projectId.toString(),
        })
            .andWhere(`"TelemetryException"."isResolved" = false`)
            .andWhere(`"TelemetryException"."isArchived" = false`)
            .andWhere(`"TelemetryException"."deletedAt" IS NULL`)
            .andWhere(`"TelemetryException"."primaryEntityId" IS NOT NULL`)
            .groupBy(`"TelemetryException"."primaryEntityId"`)
            .addGroupBy(`"TelemetryException"."primaryEntityType"`)
            .orderBy(`"unresolvedCount"`, "DESC")
            .getRawMany());
        if (rows.length === 0) {
            return [];
        }
        /*
         * primaryEntityId is polymorphic — do NOT resolve it to a Service here. The
         * old code looked each primaryEntityId up in the Service table and dropped
         * any that didn't match, which silently excluded Host / DockerHost /
         * KubernetesCluster and unattributed (Unknown) telemetry. Return the
         * raw (primaryEntityId, primaryEntityType) + counts; the client resolves the
         * display name per primaryEntityType.
         */
        const summaries = [];
        for (const row of rows) {
            if (!row.primaryEntityId) {
                continue;
            }
            summaries.push({
                primaryEntityId: row.primaryEntityId,
                primaryEntityType: (_a = row.primaryEntityType) !== null && _a !== void 0 ? _a : null,
                unresolvedCount: parseInt(row.unresolvedCount, 10) || 0,
                totalOccurrences: parseInt(row.totalOccurrences || "0", 10) || 0,
            });
        }
        return summaries;
    }
    buildFixExceptionMetadata(params) {
        const { telemetryException, telemetryExceptionId } = params;
        const metadata = {
            taskType: AIAgentTaskType.FixException,
            exceptionId: telemetryExceptionId.toString(),
        };
        if (telemetryException.stackTrace) {
            metadata.stackTrace = telemetryException.stackTrace;
        }
        if (telemetryException.message) {
            metadata.errorMessage = telemetryException.message;
        }
        if (telemetryException.primaryEntityId) {
            metadata.serviceId = telemetryException.primaryEntityId.toString();
        }
        return metadata;
    }
}
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "createAIAgentTaskForException", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID]),
    __metadata("design:returntype", Promise)
], Service.prototype, "validateNoActiveTaskExists", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "createFixExceptionTask", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "getDashboardSummary", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID, Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "aggregateUnresolvedByService", null);
export default new Service();
//# sourceMappingURL=TelemetryExceptionService.js.map