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 { IsBillingEnabled } from "../EnvironmentConfig";
import BaseService from "./BaseService";
import LlmProviderService from "./LlmProviderService";
import LlmLogService from "./LlmLogService";
import ProjectService from "./ProjectService";
import AIBillingService from "./AIBillingService";
import LLMService from "../Utils/LLM/LLMService";
import LlmLog from "../../Models/DatabaseModels/LlmLog";
import LlmLogStatus from "../../Types/LlmLogStatus";
import BadDataException from "../../Types/Exception/BadDataException";
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
import logger from "../Utils/Logger";
export class Service extends BaseService {
    constructor() {
        super();
    }
    async executeWithLogging(request) {
        var _a, _b;
        const startTime = new Date();
        // Get LLM provider for the project
        const llmProvider = await LlmProviderService.getLLMProviderForProject(request.projectId);
        if (!llmProvider) {
            throw new BadDataException("No LLM provider configured for this project. Please configure an LLM provider in Settings > AI > LLM Providers.");
        }
        if (!llmProvider.llmType) {
            throw new BadDataException("LLM provider type is not configured properly.");
        }
        // Create log entry (will be updated after completion)
        const logEntry = new LlmLog();
        logEntry.projectId = request.projectId;
        logEntry.isGlobalProvider = llmProvider.isGlobalLlm || false;
        logEntry.feature = request.feature;
        logEntry.requestPrompt = request.messages
            .map((m) => {
            return m.content;
        })
            .join("\n")
            .substring(0, 5000); // Store first 5000 chars
        logEntry.requestStartedAt = startTime;
        // Set optional fields only if they have values
        if (llmProvider.id) {
            logEntry.llmProviderId = llmProvider.id;
        }
        if (llmProvider.name) {
            logEntry.llmProviderName = llmProvider.name;
        }
        if (llmProvider.llmType) {
            logEntry.llmType = llmProvider.llmType;
        }
        if (llmProvider.modelName) {
            logEntry.modelName = llmProvider.modelName;
        }
        if (request.userId) {
            logEntry.userId = request.userId;
        }
        if (request.incidentId) {
            logEntry.incidentId = request.incidentId;
        }
        if (request.alertId) {
            logEntry.alertId = request.alertId;
        }
        if (request.scheduledMaintenanceId) {
            logEntry.scheduledMaintenanceId = request.scheduledMaintenanceId;
        }
        // Check if billing should apply
        const shouldBill = IsBillingEnabled && (llmProvider.isGlobalLlm || false);
        // Check balance if billing enabled and using global provider
        if (shouldBill) {
            const project = await ProjectService.findOneById({
                id: request.projectId,
                select: { aiCurrentBalanceInUSDCents: true },
                props: { isRoot: true },
            });
            if (!project || (project.aiCurrentBalanceInUSDCents || 0) <= 0) {
                logEntry.status = LlmLogStatus.InsufficientBalance;
                logEntry.statusMessage = "Insufficient AI balance";
                logEntry.requestCompletedAt = new Date();
                logEntry.durationMs = new Date().getTime() - startTime.getTime();
                await LlmLogService.create({
                    data: logEntry,
                    props: { isRoot: true },
                });
                throw new BadDataException("Insufficient AI balance. Please recharge your AI balance in Project Settings > AI Credits.");
            }
        }
        try {
            // Build LLM config
            const llmConfig = {
                llmType: llmProvider.llmType,
            };
            if (llmProvider.apiKey) {
                llmConfig.apiKey = llmProvider.apiKey;
            }
            if (llmProvider.baseUrl) {
                llmConfig.baseUrl = llmProvider.baseUrl.toString();
            }
            if (llmProvider.modelName) {
                llmConfig.modelName = llmProvider.modelName;
            }
            // Execute LLM call
            const response = await LLMService.getCompletion({
                llmProviderConfig: llmConfig,
                messages: request.messages,
                temperature: (_a = request.temperature) !== null && _a !== void 0 ? _a : 0.7,
            });
            const endTime = new Date();
            // Update log with success info
            logEntry.status = LlmLogStatus.Success;
            logEntry.totalTokens = ((_b = response.usage) === null || _b === void 0 ? void 0 : _b.totalTokens) || 0;
            logEntry.responsePreview = response.content.substring(0, 2000); // Store first 2000 chars
            logEntry.requestCompletedAt = endTime;
            logEntry.durationMs = endTime.getTime() - startTime.getTime();
            // Calculate and apply costs if using global provider with billing enabled
            if (shouldBill && response.usage) {
                const totalCost = Math.ceil((response.usage.totalTokens / 1000000) *
                    (llmProvider.costPerMillionTokensInUSDCents || 0));
                logEntry.costInUSDCents = totalCost;
                logEntry.wasBilled = true;
                // Deduct from project balance
                if (totalCost > 0) {
                    const project = await ProjectService.findOneById({
                        id: request.projectId,
                        select: { aiCurrentBalanceInUSDCents: true },
                        props: { isRoot: true },
                    });
                    if (project) {
                        const newBalance = Math.max(0, (project.aiCurrentBalanceInUSDCents || 0) - totalCost);
                        await ProjectService.updateOneById({
                            id: request.projectId,
                            data: {
                                aiCurrentBalanceInUSDCents: newBalance,
                            },
                            props: { isRoot: true },
                        });
                    }
                    // Check if auto-recharge is needed (do this async, don't wait)
                    AIBillingService.rechargeIfBalanceIsLow(request.projectId).catch((err) => {
                        var _a, _b, _c, _d;
                        logger.error("Error during AI balance auto-recharge check:", {
                            projectId: (_a = request.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                            userId: (_b = request.userId) === null || _b === void 0 ? void 0 : _b.toString(),
                        });
                        logger.error(err, {
                            projectId: (_c = request.projectId) === null || _c === void 0 ? void 0 : _c.toString(),
                            userId: (_d = request.userId) === null || _d === void 0 ? void 0 : _d.toString(),
                        });
                    });
                }
            }
            // Save log entry
            const savedLog = await LlmLogService.create({
                data: logEntry,
                props: { isRoot: true },
            });
            return {
                content: response.content,
                llmLog: savedLog,
            };
        }
        catch (error) {
            // Log the error
            logEntry.status = LlmLogStatus.Error;
            logEntry.statusMessage =
                error instanceof Error ? error.message : String(error);
            logEntry.requestCompletedAt = new Date();
            logEntry.durationMs = new Date().getTime() - startTime.getTime();
            await LlmLogService.create({
                data: logEntry,
                props: { isRoot: true },
            });
            throw error;
        }
    }
}
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "executeWithLogging", null);
export default new Service();
//# sourceMappingURL=AIService.js.map