"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.clickhouseApplicationsService = exports.ClickhouseApplicationsService = void 0;
const drizzle_orm_1 = require("drizzle-orm");
const database_1 = require("../../database");
const tables_1 = require("../../database/tables");
const logger_1 = __importDefault(require("../../logger"));
const clickhouseService_1 = require("./clickhouseService");
const CLICKHOUSE_APPLICATIONS_TABLE = 'applications';
/**
 * ClickHouse JSONEachRow + default date_time_input_format does not reliably parse
 * ISO-8601 with `T`/`Z` for DateTime64; use space-separated UTC (matches basic parser).
 */
const toDateTime64 = (d) => {
    const date = d instanceof Date ? d : d ? new Date(String(d)) : new Date();
    const t = Number.isNaN(date.getTime()) ? new Date() : date;
    return t.toISOString().replace('T', ' ').replace(/Z$/, '');
};
const toJsonString = (v) => {
    try {
        if (typeof v === 'string') {
            return v;
        }
        return JSON.stringify(v ?? {});
    }
    catch {
        return '{}';
    }
};
class ClickhouseApplicationsService {
    async ensureTable() {
        // Use ReplacingMergeTree so we can "upsert" by inserting a new version.
        // Consumers should query with FINAL or use argMax(updated_at, ...) when needed.
        const ddl = `
      CREATE TABLE IF NOT EXISTS ${CLICKHOUSE_APPLICATIONS_TABLE} (
        id String,
        created_at DateTime64(3, 'UTC'),
        updated_at DateTime64(3, 'UTC'),
        name Nullable(String),
        description Nullable(String),
        status Nullable(Int32),
        security_config String,
        use_case Nullable(String),
        provider_config String,
        project_id String,
        workspace_id Nullable(String),
        test_runs Nullable(Int32),
        provider_type Nullable(String),
        is_archived UInt8,
        enable_encryption Nullable(String),
        is_agentic UInt8,
        monitoring_enabled UInt8,
        guardrails_enabled UInt8
      )
      ENGINE = ReplacingMergeTree(updated_at)
      PARTITION BY toYYYYMM(created_at)
      ORDER BY (project_id, id)
    `;
        await clickhouseService_1.clickHouseService.command(ddl);
    }
    async upsertFromPostgres(applicationId) {
        const db = await (0, database_1.getDb)();
        const [app] = await db.select().from(tables_1.applicationsTable).where((0, drizzle_orm_1.eq)(tables_1.applicationsTable.id, applicationId)).limit(1);
        if (!app) {
            throw new Error('Application not found');
        }
        const [monitoring] = await db
            .select({ id: tables_1.pulseMonitoringTable.id })
            .from(tables_1.pulseMonitoringTable)
            .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, applicationId))
            .limit(1);
        const [guardrails] = await db
            .select({ enable_guard_rails: tables_1.applicationGuardrailsTable.enable_guard_rails })
            .from(tables_1.applicationGuardrailsTable)
            .where((0, drizzle_orm_1.eq)(tables_1.applicationGuardrailsTable.applicationId, applicationId))
            .limit(1);
        const row = {
            id: String(app.id),
            created_at: toDateTime64(app.createdAt),
            updated_at: toDateTime64(app.updatedAt),
            name: app.name ?? null,
            description: app.description ?? null,
            status: app.status ?? null,
            security_config: toJsonString(app.security_config),
            use_case: app.useCase ?? null,
            provider_config: toJsonString(app.provider_config),
            project_id: app.projectId ?? null,
            workspace_id: app.workspaceId ?? null,
            test_runs: app.test_runs ?? null,
            provider_type: app.provider_type ?? null,
            is_archived: app.is_archived ? 1 : 0,
            enable_encryption: app.enableEncryption ?? null,
            is_agentic: app.isAgentic ? 1 : 0,
            monitoring_enabled: monitoring?.id ? 1 : 0,
            guardrails_enabled: guardrails?.enable_guard_rails ? 1 : 0,
        };
        await this.ensureTable();
        await clickhouseService_1.clickHouseService.insert(CLICKHOUSE_APPLICATIONS_TABLE, [row]);
    }
    async migrateAllFromPostgres() {
        const db = await (0, database_1.getDb)();
        await this.ensureTable();
        const apps = await db.select().from(tables_1.applicationsTable);
        if (apps.length === 0) {
            return { inserted: 0 };
        }
        // Preload monitoring + guardrails flags to avoid N+1 queries.
        const appIds = apps.map((a) => String(a.id));
        const monitoringRows = await db
            .select({ applicationId: tables_1.pulseMonitoringTable.applicationId })
            .from(tables_1.pulseMonitoringTable)
            .where((0, drizzle_orm_1.inArray)(tables_1.pulseMonitoringTable.applicationId, appIds));
        const monitoringSet = new Set(monitoringRows.map((m) => String(m.applicationId)));
        const guardrailsRows = await db.select().from(tables_1.applicationGuardrailsTable);
        const guardrailsByApp = new Map();
        for (const g of guardrailsRows) {
            if (g?.applicationId) {
                guardrailsByApp.set(String(g.applicationId), Boolean(g.enable_guard_rails));
            }
        }
        const rows = [];
        for (const app of apps) {
            if (app?.is_archived) {
                continue;
            }
            const id = String(app.id);
            const monitoringEnabled = monitoringSet.has(id) ? 1 : 0;
            rows.push({
                id,
                created_at: toDateTime64(app.createdAt),
                updated_at: toDateTime64(app.updatedAt),
                name: app.name ?? null,
                description: app.description ?? null,
                status: app.status ?? null,
                security_config: toJsonString(app.security_config),
                use_case: app.useCase ?? null,
                provider_config: toJsonString(app.provider_config),
                project_id: String(app.projectId ?? ''),
                workspace_id: app.workspaceId ?? null,
                test_runs: app.test_runs ?? null,
                provider_type: app.provider_type ?? null,
                is_archived: app.is_archived ? 1 : 0,
                enable_encryption: app.enableEncryption ?? null,
                is_agentic: app.isAgentic ? 1 : 0,
                monitoring_enabled: monitoringEnabled,
                guardrails_enabled: guardrailsByApp.get(id) ? 1 : 0,
            });
        }
        // Insert in chunks to avoid huge payloads.
        const CHUNK = 500;
        for (let i = 0; i < rows.length; i += CHUNK) {
            const chunk = rows.slice(i, i + CHUNK);
            await clickhouseService_1.clickHouseService.insert(CLICKHOUSE_APPLICATIONS_TABLE, chunk);
        }
        logger_1.default.info(`Migrated ${rows.length} applications to ClickHouse`);
        return { inserted: rows.length };
    }
}
exports.ClickhouseApplicationsService = ClickhouseApplicationsService;
exports.clickhouseApplicationsService = new ClickhouseApplicationsService();
//# sourceMappingURL=clickhouseApplicationsService.js.map