import { Injectable } from '@nestjs/common'; interface MockBackupShare { shareId: bigint; userId: bigint; accountSequence: bigint; publicKey: string; partyIndex: number; threshold: number; totalParties: number; encryptedShareData: string; encryptionKeyId: string; status: string; accessCount: number; lastAccessedAt: Date | null; createdAt: Date; updatedAt: Date; revokedAt: Date | null; } interface MockShareAccessLog { logId: bigint; shareId: bigint; userId: bigint; action: string; sourceService: string; sourceIp: string; success: boolean; errorMessage: string | null; createdAt: Date; } @Injectable() export class MockPrismaService { private backupShares: MockBackupShare[] = []; private shareAccessLogs: MockShareAccessLog[] = []; private shareIdCounter = 1n; private logIdCounter = 1n; backupShare = { create: jest.fn().mockImplementation(({ data }) => { const share: MockBackupShare = { shareId: this.shareIdCounter++, userId: data.userId, accountSequence: data.accountSequence, publicKey: data.publicKey, partyIndex: data.partyIndex ?? 2, threshold: data.threshold ?? 2, totalParties: data.totalParties ?? 3, encryptedShareData: data.encryptedShareData, encryptionKeyId: data.encryptionKeyId, status: data.status ?? 'ACTIVE', accessCount: data.accessCount ?? 0, lastAccessedAt: data.lastAccessedAt ?? null, createdAt: new Date(), updatedAt: new Date(), revokedAt: data.revokedAt ?? null, }; this.backupShares.push(share); return Promise.resolve(share); }), update: jest.fn().mockImplementation(({ where, data }) => { const index = this.backupShares.findIndex(s => s.shareId === where.shareId); if (index === -1) return Promise.resolve(null); this.backupShares[index] = { ...this.backupShares[index], ...data, updatedAt: new Date(), }; return Promise.resolve(this.backupShares[index]); }), findUnique: jest.fn().mockImplementation(({ where }) => { let share: MockBackupShare | undefined; if (where.shareId) { share = this.backupShares.find(s => s.shareId === where.shareId); } else if (where.userId) { share = this.backupShares.find(s => s.userId === where.userId); } else if (where.publicKey) { share = this.backupShares.find(s => s.publicKey === where.publicKey); } else if (where.accountSequence) { share = this.backupShares.find(s => s.accountSequence === where.accountSequence); } return Promise.resolve(share ?? null); }), findFirst: jest.fn().mockImplementation(({ where }) => { const share = this.backupShares.find(s => s.userId === where.userId && s.publicKey === where.publicKey ); return Promise.resolve(share ?? null); }), delete: jest.fn().mockImplementation(({ where }) => { const index = this.backupShares.findIndex(s => s.shareId === where.shareId); if (index === -1) return Promise.resolve(null); const deleted = this.backupShares.splice(index, 1)[0]; return Promise.resolve(deleted); }), deleteMany: jest.fn().mockImplementation(() => { const count = this.backupShares.length; this.backupShares = []; return Promise.resolve({ count }); }), }; shareAccessLog = { create: jest.fn().mockImplementation(({ data }) => { const log: MockShareAccessLog = { logId: this.logIdCounter++, shareId: data.shareId, userId: data.userId, action: data.action, sourceService: data.sourceService, sourceIp: data.sourceIp, success: data.success ?? true, errorMessage: data.errorMessage ?? null, createdAt: new Date(), }; this.shareAccessLogs.push(log); return Promise.resolve(log); }), findMany: jest.fn().mockImplementation(({ where, orderBy, take }) => { let logs = [...this.shareAccessLogs]; if (where?.shareId) { logs = logs.filter(l => l.shareId === where.shareId); } if (where?.userId) { logs = logs.filter(l => l.userId === where.userId); } if (orderBy?.createdAt === 'desc') { logs.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()); } if (take) { logs = logs.slice(0, take); } return Promise.resolve(logs); }), count: jest.fn().mockImplementation(({ where }) => { let logs = [...this.shareAccessLogs]; if (where?.userId) { logs = logs.filter(l => l.userId === where.userId); } if (where?.action) { logs = logs.filter(l => l.action === where.action); } if (where?.createdAt?.gte) { logs = logs.filter(l => l.createdAt >= where.createdAt.gte); } return Promise.resolve(logs.length); }), deleteMany: jest.fn().mockImplementation(() => { const count = this.shareAccessLogs.length; this.shareAccessLogs = []; return Promise.resolve({ count }); }), }; $connect = jest.fn().mockResolvedValue(undefined); $disconnect = jest.fn().mockResolvedValue(undefined); $queryRaw = jest.fn().mockResolvedValue([{ '?column?': 1 }]); // Helper methods for testing reset(): void { this.backupShares = []; this.shareAccessLogs = []; this.shareIdCounter = 1n; this.logIdCounter = 1n; jest.clearAllMocks(); } getBackupShares(): MockBackupShare[] { return [...this.backupShares]; } getShareAccessLogs(): MockShareAccessLog[] { return [...this.shareAccessLogs]; } }