import { and, desc, eq, isNull, or, sql } from "drizzle-orm";
import { activityLog, heartbeatRuns, issues } from "@zmeel/db";
export function activityService(db) {
    const issueIdAsText = sql `${issues.id}::text`;
    return {
        list: (filters) => {
            const conditions = [eq(activityLog.companyId, filters.companyId)];
            if (filters.agentId) {
                conditions.push(eq(activityLog.agentId, filters.agentId));
            }
            if (filters.entityType) {
                conditions.push(eq(activityLog.entityType, filters.entityType));
            }
            if (filters.entityId) {
                conditions.push(eq(activityLog.entityId, filters.entityId));
            }
            return db
                .select({ activityLog })
                .from(activityLog)
                .leftJoin(issues, and(eq(activityLog.entityType, sql `'issue'`), eq(activityLog.entityId, issueIdAsText)))
                .where(and(...conditions, or(sql `${activityLog.entityType} != 'issue'`, isNull(issues.hiddenAt))))
                .orderBy(desc(activityLog.createdAt))
                .then((rows) => rows.map((r) => r.activityLog));
        },
        forIssue: (issueId) => db
            .select()
            .from(activityLog)
            .where(and(eq(activityLog.entityType, "issue"), eq(activityLog.entityId, issueId)))
            .orderBy(desc(activityLog.createdAt)),
        runsForIssue: (companyId, issueId) => db
            .select({
            runId: heartbeatRuns.id,
            status: heartbeatRuns.status,
            agentId: heartbeatRuns.agentId,
            startedAt: heartbeatRuns.startedAt,
            finishedAt: heartbeatRuns.finishedAt,
            createdAt: heartbeatRuns.createdAt,
            invocationSource: heartbeatRuns.invocationSource,
            usageJson: heartbeatRuns.usageJson,
            resultJson: heartbeatRuns.resultJson,
        })
            .from(heartbeatRuns)
            .where(and(eq(heartbeatRuns.companyId, companyId), or(sql `${heartbeatRuns.contextSnapshot} ->> 'issueId' = ${issueId}`, sql `exists (
                select 1
                from ${activityLog}
                where ${activityLog.companyId} = ${companyId}
                  and ${activityLog.entityType} = 'issue'
                  and ${activityLog.entityId} = ${issueId}
                  and ${activityLog.runId} = ${heartbeatRuns.id}
              )`)))
            .orderBy(desc(heartbeatRuns.createdAt)),
        issuesForRun: async (runId) => {
            const run = await db
                .select({
                companyId: heartbeatRuns.companyId,
                contextSnapshot: heartbeatRuns.contextSnapshot,
            })
                .from(heartbeatRuns)
                .where(eq(heartbeatRuns.id, runId))
                .then((rows) => rows[0] ?? null);
            if (!run)
                return [];
            const fromActivity = await db
                .selectDistinctOn([issueIdAsText], {
                issueId: issues.id,
                identifier: issues.identifier,
                title: issues.title,
                status: issues.status,
                priority: issues.priority,
            })
                .from(activityLog)
                .innerJoin(issues, eq(activityLog.entityId, issueIdAsText))
                .where(and(eq(activityLog.companyId, run.companyId), eq(activityLog.runId, runId), eq(activityLog.entityType, "issue"), isNull(issues.hiddenAt)))
                .orderBy(issueIdAsText);
            const context = run.contextSnapshot;
            const contextIssueId = context && typeof context === "object" && typeof context.issueId === "string"
                ? context.issueId
                : null;
            if (!contextIssueId)
                return fromActivity;
            if (fromActivity.some((issue) => issue.issueId === contextIssueId))
                return fromActivity;
            const fromContext = await db
                .select({
                issueId: issues.id,
                identifier: issues.identifier,
                title: issues.title,
                status: issues.status,
                priority: issues.priority,
            })
                .from(issues)
                .where(and(eq(issues.companyId, run.companyId), eq(issues.id, contextIssueId), isNull(issues.hiddenAt)))
                .then((rows) => rows[0] ?? null);
            if (!fromContext)
                return fromActivity;
            return [fromContext, ...fromActivity];
        },
        create: (data) => db
            .insert(activityLog)
            .values(data)
            .returning()
            .then((rows) => rows[0]),
    };
}
//# sourceMappingURL=activity.js.map