import { describe, it, beforeEach, expect, vi } from 'vitest';
import { generateAiGuide } from '../../src/commands/guide-ai';
import type { Logger } from '../../src/services/console-logger';

// Mock fs-extra
vi.mock('fs-extra', () => ({
  default: {
    readdir: vi.fn().mockResolvedValue([]),
    stat: vi.fn().mockResolvedValue({ isDirectory: () => true }),
    writeFile: vi.fn().mockResolvedValue(undefined),
    ensureDir: vi.fn().mockResolvedValue(undefined),
  },
  readdir: vi.fn().mockResolvedValue([]),
  stat: vi.fn().mockResolvedValue({ isDirectory: () => true }),
  writeFile: vi.fn().mockResolvedValue(undefined),
  ensureDir: vi.fn().mockResolvedValue(undefined),
}));

// Mock console.warn
const mockConsoleWarn = vi.spyOn(console, 'warn').mockImplementation(() => {});

// Mock process.cwd
vi.spyOn(process, 'cwd').mockReturnValue('/test/project');

describe('guide-ai command', () => {
  let mockLogger: Logger;

  beforeEach(() => {
    vi.clearAllMocks();
    
    // Create fresh mock logger for each test
    mockLogger = {
      info: vi.fn(),
      success: vi.fn(),
      warning: vi.fn(),
      error: vi.fn(),
      log: vi.fn(),
    };
  });

  describe('basic functionality', () => {
    it('should generate guide files successfully', async () => {
      await generateAiGuide(mockLogger, []);

      expect(mockLogger.info).toHaveBeenCalledWith('🤖 Generating AI tools guide...');
      expect(mockLogger.success).toHaveBeenCalledWith('🎉 AI tools guide generated successfully!');
    });

    it('should handle domain analysis', async () => {
      const fs = await import('fs-extra');
      vi.mocked(fs.readdir).mockResolvedValueOnce(['user', 'product'] as any);

      await generateAiGuide(mockLogger, []);

      // Vérifier que l'analyse de la structure a été loggée
      expect(mockLogger.info).toHaveBeenCalledWith('📊 Analyzing project structure...');
    });

    it('should handle missing domains folder gracefully', async () => {
      const fs = await import('fs-extra');
      vi.mocked(fs.readdir).mockRejectedValueOnce(new Error('ENOENT'));

      await generateAiGuide(mockLogger, []);

      // Vérifier que le processus continue malgré l'erreur
      expect(mockLogger.success).toHaveBeenCalledWith('🎉 AI tools guide generated successfully!');
    });
  });

  describe('tool configurations', () => {
    it('should generate Cursor configuration', async () => {
      await generateAiGuide(mockLogger, ['cursor']);

      expect(mockLogger.info).toHaveBeenCalledWith(
        '🔧 Generating configurations for AI tools: cursor...'
      );
      expect(mockLogger.success).toHaveBeenCalledWith(
        '✅ Tool configurations generated for: cursor'
      );
    });

    it('should generate multiple tool configurations', async () => {
      await generateAiGuide(mockLogger, ['cursor', 'copilot']);

      expect(mockLogger.info).toHaveBeenCalledWith(
        '🔧 Generating configurations for AI tools: cursor, copilot...'
      );
      expect(mockLogger.success).toHaveBeenCalledWith(
        '✅ Tool configurations generated for: cursor, copilot'
      );
    });

    it('should warn about unknown tools', async () => {
      await generateAiGuide(mockLogger, ['unknown-tool']);

      expect(mockConsoleWarn).toHaveBeenCalledWith(
        expect.stringContaining('Warning: Unknown tool "unknown-tool"')
      );
    });

    it('should accept all supported tools', async () => {
      await generateAiGuide(mockLogger, ['cursor', 'copilot', 'windsurf', 'juni']);

      expect(mockLogger.success).toHaveBeenCalledWith(
        '✅ Tool configurations generated for: cursor, copilot, windsurf, juni'
      );
    });
  });

  describe('domain guides generation', () => {
    it('should complete successfully even with domain analysis', async () => {
      const fs = await import('fs-extra');
      vi.mocked(fs.readdir).mockResolvedValueOnce(['user', 'product'] as any);

      await generateAiGuide(mockLogger, []);

      // Vérifier que le processus s'est terminé avec succès
      expect(mockLogger.success).toHaveBeenCalledWith('🎉 AI tools guide generated successfully!');
    });

    it('should skip domain guides when no domains exist', async () => {
      const fs = await import('fs-extra');
      vi.mocked(fs.readdir).mockResolvedValueOnce([] as any);

      await generateAiGuide(mockLogger, []);

      // Pas de guides de domaines générés car aucun domaine détecté
      expect(mockLogger.success).toHaveBeenCalledWith('🎉 AI tools guide generated successfully!');
    });
  });

  describe('file writing', () => {
    it('should write configuration files', async () => {
      await generateAiGuide(mockLogger, []);

      // Vérifier que le processus de génération s'est bien déroulé
      expect(mockLogger.info).toHaveBeenCalledWith('📝 Generating configuration file...');
      expect(mockLogger.success).toHaveBeenCalledWith('✅ ruch-guide.json generated');
    });

    it('should write global guide file', async () => {
      await generateAiGuide(mockLogger, []);

      // Vérifier que le guide global a été généré
      expect(mockLogger.info).toHaveBeenCalledWith('📚 Generating global guide...');
      expect(mockLogger.success).toHaveBeenCalledWith('✅ GUIDE.md generated');
    });

    it('should handle tool configurations', async () => {
      await generateAiGuide(mockLogger, ['copilot', 'juni']);

      // Vérifier que les configurations d'outils ont été traitées
      expect(mockLogger.info).toHaveBeenCalledWith(
        expect.stringContaining('Generating configurations for AI tools')
      );
      expect(mockLogger.success).toHaveBeenCalledWith(
        expect.stringContaining('Tool configurations generated for')
      );
    });
  });

  describe('error handling', () => {
    it('should handle errors gracefully in most cases', async () => {
      const fs = await import('fs-extra');
      vi.mocked(fs.readdir).mockRejectedValueOnce(new Error('ENOENT'));

      await generateAiGuide(mockLogger, []);
      
      // Le processus doit continuer malgré l'erreur de lecture des domaines
      expect(mockLogger.success).toHaveBeenCalledWith('🎉 AI tools guide generated successfully!');
    });

    it('should handle domain analysis errors gracefully', async () => {
      const fs = await import('fs-extra');
      vi.mocked(fs.readdir).mockResolvedValueOnce(['user'] as any);
      vi.mocked(fs.stat).mockRejectedValueOnce(new Error('Stat error'));

      await generateAiGuide(mockLogger, []);
      
      expect(mockLogger.success).toHaveBeenCalledWith('🎉 AI tools guide generated successfully!');
    });
  });
}); 