/**
 * Tests unitaires pour database.ts
 */

/* eslint-disable @typescript-eslint/no-explicit-any */
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import {
  testDatabaseConnection,
  closeDatabaseConnection,
  clearDatabase,
  prisma,
} from '../database';

describe('database utilities', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('testDatabaseConnection', () => {
    it('devrait retourner true si la connexion réussit', async () => {
      vi.spyOn(prisma, '$connect').mockResolvedValue(undefined);

      const result = await testDatabaseConnection();

      expect(result).toBe(true);
      expect(prisma.$connect).toHaveBeenCalled();
    });

    it('devrait retourner false si la connexion échoue', async () => {
      vi.spyOn(prisma, '$connect').mockRejectedValue(
        new Error('Connection failed')
      );

      const result = await testDatabaseConnection();

      expect(result).toBe(false);
    });
  });

  describe('closeDatabaseConnection', () => {
    it('devrait fermer la connexion avec succès', async () => {
      vi.spyOn(prisma, '$disconnect').mockResolvedValue(undefined);

      await closeDatabaseConnection();

      expect(prisma.$disconnect).toHaveBeenCalled();
    });

    it('devrait gérer les erreurs lors de la fermeture', async () => {
      vi.spyOn(prisma, '$disconnect').mockRejectedValue(
        new Error('Disconnect failed')
      );

      // Ne devrait pas throw
      await expect(closeDatabaseConnection()).resolves.not.toThrow();
    });
  });

  describe('clearDatabase', () => {
    beforeEach(() => {
      // S'assurer qu'on est pas en production
      vi.stubEnv('NODE_ENV', 'test');
    });

    afterEach(() => {
      vi.unstubAllEnvs();
    });

    it('devrait nettoyer toutes les tables', async () => {
      const deleteManySpy = vi.fn().mockResolvedValue({ count: 0 });

      // Mock des méthodes deleteMany directement
      (prisma.taskTag as any) = { deleteMany: deleteManySpy };
      (prisma.task as any) = { deleteMany: deleteManySpy };
      (prisma.tag as any) = { deleteMany: deleteManySpy };
      (prisma.syncLog as any) = { deleteMany: deleteManySpy };

      await clearDatabase();

      expect(deleteManySpy).toHaveBeenCalledTimes(4);
    });

    it('ne devrait pas permettre le nettoyage en production', async () => {
      vi.stubEnv('NODE_ENV', 'production');

      await expect(clearDatabase()).rejects.toThrow(
        'Cannot clear database in production'
      );

      vi.unstubAllEnvs();
    });
  });
});
