/**
 * Audit Search Tests
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import {
  searchAuditLogs,
  getAuditStatistics,
  exportAuditLogs,
  AuditSearchFilters,
} from './audit-search';
import { query } from './client';

vi.mock('./client');

describe('Audit Search', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('searchAuditLogs', () => {
    it('should search audit logs with filters', async () => {
      const filters: AuditSearchFilters = {
        credentialId: 'test-credential-id',
        issuerDid: 'did:web:example.com',
        action: 'issued',
      };

      const mockLogs = [
        {
          id: 'audit-id',
          credential_id: 'test-credential-id',
          issuer_did: 'did:web:example.com',
          subject_did: 'did:web:subject.com',
          credential_type: ['VerifiableCredential'],
          action: 'issued' as const,
          performed_at: new Date(),
        },
      ];

      const mockCountResult = {
        rows: [{ count: '1' }],
      };

      const mockLogResult = {
        rows: mockLogs,
      };

      vi.mocked(query)
        .mockResolvedValueOnce(mockCountResult as any)
        .mockResolvedValueOnce(mockLogResult as any);

      const result = await searchAuditLogs(filters, 1, 50);

      expect(result.logs).toEqual(mockLogs);
      expect(result.total).toBe(1);
      expect(result.page).toBe(1);
      expect(result.pageSize).toBe(50);
      expect(query).toHaveBeenCalledTimes(2);
    });

    it('should search audit logs with date range', async () => {
      const filters: AuditSearchFilters = {
        startDate: new Date('2024-01-01'),
        endDate: new Date('2024-12-31'),
      };

      const mockCountResult = {
        rows: [{ count: '0' }],
      };

      const mockLogResult = {
        rows: [],
      };

      vi.mocked(query)
        .mockResolvedValueOnce(mockCountResult as any)
        .mockResolvedValueOnce(mockLogResult as any);

      const result = await searchAuditLogs(filters, 1, 50);

      expect(result.logs).toEqual([]);
      expect(result.total).toBe(0);
    });

    it('should search audit logs with credential type array', async () => {
      const filters: AuditSearchFilters = {
        credentialType: ['VerifiableCredential', 'IdentityCredential'],
      };

      const mockCountResult = {
        rows: [{ count: '2' }],
      };

      const mockLogResult = {
        rows: [],
      };

      vi.mocked(query)
        .mockResolvedValueOnce(mockCountResult as any)
        .mockResolvedValueOnce(mockLogResult as any);

      const result = await searchAuditLogs(filters, 1, 50);

      expect(result.total).toBe(2);
    });
  });

  describe('getAuditStatistics', () => {
    it('should get audit statistics', async () => {
      const mockActionResult = {
        rows: [
          { action: 'issued', count: '10' },
          { action: 'revoked', count: '2' },
          { action: 'verified', count: '5' },
        ],
      };

      const mockTypeResult = {
        rows: [
          { credential_type: ['VerifiableCredential', 'IdentityCredential'], count: '8' },
          { credential_type: ['VerifiableCredential', 'JudicialCredential'], count: '4' },
        ],
      };

      vi.mocked(query)
        .mockResolvedValueOnce(mockActionResult as any)
        .mockResolvedValueOnce(mockTypeResult as any);

      const result = await getAuditStatistics();

      expect(result.totalIssuances).toBe(10);
      expect(result.totalRevocations).toBe(2);
      expect(result.totalVerifications).toBe(5);
      expect(result.byAction.issued).toBe(10);
      expect(result.byCredentialType).toBeDefined();
    });

    it('should get audit statistics with date range', async () => {
      const startDate = new Date('2024-01-01');
      const endDate = new Date('2024-12-31');

      const mockActionResult = {
        rows: [{ action: 'issued', count: '5' }],
      };

      const mockTypeResult = {
        rows: [],
      };

      vi.mocked(query)
        .mockResolvedValueOnce(mockActionResult as any)
        .mockResolvedValueOnce(mockTypeResult as any);

      const result = await getAuditStatistics(startDate, endDate);

      expect(result.totalIssuances).toBe(5);
    });
  });

  describe('exportAuditLogs', () => {
    it('should export audit logs as JSON', async () => {
      const filters: AuditSearchFilters = {
        action: 'issued',
      };

      const mockLogs = [
        {
          id: 'audit-id',
          credential_id: 'test-credential-id',
          issuer_did: 'did:web:example.com',
          subject_did: 'did:web:subject.com',
          credential_type: ['VerifiableCredential'],
          action: 'issued' as const,
          performed_by: 'admin-user-id',
          performed_at: new Date('2024-01-01'),
          ip_address: '127.0.0.1',
          user_agent: 'test-agent',
        },
      ];

      const mockCountResult = {
        rows: [{ count: '1' }],
      };

      const mockLogResult = {
        rows: mockLogs,
      };

      vi.mocked(query)
        .mockResolvedValueOnce(mockCountResult as any)
        .mockResolvedValueOnce(mockLogResult as any);

      const result = await exportAuditLogs(filters, 'json');

      expect(result).toContain('audit-id');
      expect(result).toContain('test-credential-id');
      expect(JSON.parse(result)).toHaveLength(1);
    });

    it('should export audit logs as CSV', async () => {
      const filters: AuditSearchFilters = {
        action: 'issued',
      };

      const mockLogs = [
        {
          id: 'audit-id',
          credential_id: 'test-credential-id',
          issuer_did: 'did:web:example.com',
          subject_did: 'did:web:subject.com',
          credential_type: ['VerifiableCredential'],
          action: 'issued' as const,
          performed_by: 'admin-user-id',
          performed_at: new Date('2024-01-01'),
          ip_address: '127.0.0.1',
          user_agent: 'test-agent',
        },
      ];

      const mockCountResult = {
        rows: [{ count: '1' }],
      };

      const mockLogResult = {
        rows: mockLogs,
      };

      vi.mocked(query)
        .mockResolvedValueOnce(mockCountResult as any)
        .mockResolvedValueOnce(mockLogResult as any);

      const result = await exportAuditLogs(filters, 'csv');

      expect(result).toContain('id,credential_id,issuer_did');
      expect(result).toContain('audit-id');
      expect(result).toContain('test-credential-id');
    });
  });
});

