/**
 * @fileoverview Tests for the Vercel deployment adapter
 */

import { describe, expect, it, vi } from 'vitest';
import * as fs from '../../fs.js';
import { VercelAdapter } from './vercel-adapter.js';

// Mock the fs module
vi.mock('../../fs.js', () => ({
  readFile: vi.fn(),
  writeFile: vi.fn(),
  mkdir: vi.fn()
}));

// Mock the asset optimizer
vi.mock('../../asset-optimizer.js', () => ({
  AssetOptimizer: vi.fn().mockImplementation(() => ({
    optimizeDirectory: vi.fn().mockResolvedValue({
      assets: [],
      totalOriginalSize: 100,
      totalMinifiedSize: 50,
      totalGzipSize: 30,
      totalBrotliSize: 20,
      overallCompressionRatio: 0.5,
      totalOriginalSizeHuman: '100 B',
      totalMinifiedSizeHuman: '50 B',
      totalGzipSizeHuman: '30 B',
      totalBrotliSizeHuman: '20 B'
    }),
    generateSizeReport: vi.fn().mockReturnValue('Size report')
  }))
}));

describe('VercelAdapter', () => {
  it('should validate configuration correctly', () => {
    const adapter = new VercelAdapter();

    // Valid configuration
    const validConfig = {
      outputDir: 'dist',
      settings: {
        projectName: 'my-project'
      }
    };

    expect(adapter.validateConfig(validConfig).valid).toBe(true);

    // Invalid configuration - missing outputDir
    const invalidConfig1 = {
      settings: {
        projectName: 'my-project'
      }
    };

    expect(adapter.validateConfig(invalidConfig1).valid).toBe(false);

    // Invalid configuration - invalid project name
    const invalidConfig2 = {
      outputDir: 'dist',
      settings: {
        projectName: 'MY PROJECT!'
      }
    };

    expect(adapter.validateConfig(invalidConfig2).valid).toBe(false);
  });

  it('should prepare deployment correctly', async () => {
    const adapter = new VercelAdapter();

    // Mock writeFile and mkdir
    vi.mocked(fs.writeFile).mockResolvedValue(undefined);
    vi.mocked(fs.mkdir).mockResolvedValue(undefined);

    const config = {
      outputDir: 'dist',
      settings: {
        projectName: 'my-project'
      }
    };

    const result = await adapter.prepareDeployment(config);

    expect(result.success).toBe(true);
    expect(result.generatedFiles.length).toBeGreaterThan(0);
    expect(result.instructions).toContain('Vercel Deployment Instructions');

    // Check that writeFile was called for vercel.json
    expect(vi.mocked(fs.writeFile)).toHaveBeenCalledWith(
      expect.stringContaining('vercel.json'),
      expect.any(String)
    );

    // Check that mkdir was called
    expect(vi.mocked(fs.mkdir)).toHaveBeenCalled();
  });

  it('should handle deployment preparation errors', async () => {
    const adapter = new VercelAdapter();

    // Mock writeFile to throw an error
    vi.mocked(fs.writeFile).mockRejectedValue(new Error('Write error'));

    const config = {
      outputDir: 'dist',
      settings: {
        projectName: 'my-project'
      }
    };

    const result = await adapter.prepareDeployment(config);

    expect(result.success).toBe(false);
    expect(result.error).toContain('Write error');
  });

  it('should optimize for deployment correctly', async () => {
    const adapter = new VercelAdapter();

    const config = {
      outputDir: 'dist',
      settings: {
        projectName: 'my-project'
      }
    };

    const result = await adapter.optimizeForDeployment(config, 'dist');

    expect(result.totalOriginalSize).toBe(100);
    expect(result.totalMinifiedSize).toBe(50);
    expect(result.totalGzipSize).toBe(30);
    expect(result.totalBrotliSize).toBe(20);
  });

  it('should get environment variables correctly', () => {
    const adapter = new VercelAdapter();

    const config = {
      outputDir: 'dist',
      env: {
        API_URL: 'https://api.example.com'
      },
      domain: {
        name: 'example.com',
        useHttps: true
      }
    };

    const env = adapter.getEnvironmentVariables(config);

    expect(env.VERCEL).toBe('1');
    expect(env.NODE_ENV).toBe('production');
    expect(env.API_URL).toBe('https://api.example.com');
    expect(env.VERCEL_URL).toBe('example.com');
  });

  it('should get deploy command correctly', () => {
    const adapter = new VercelAdapter();

    const config = {
      outputDir: 'dist'
    };

    const command = adapter.getDeployCommand(config);

    expect(command).toContain('vercel --prod');
    expect(command).toContain('dist');
  });
});
