/**
 * Build Output Structure Tests
 * 
 * Tests to verify the build process creates the correct output structure
 */

import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { existsSync, statSync, readdirSync } from 'node:fs';
import { join } from 'node:path';

describe('Build Output Structure', () => {
  const distDir = join(process.cwd(), 'dist');
  
  it('should create dist directory after build', () => {
    // This test will check if dist directory exists
    // (will pass after build is run)
    if (existsSync(distDir)) {
      assert.equal(existsSync(distDir), true);
      assert.equal(statSync(distDir).isDirectory(), true);
    } else {
      // Skip test if build hasn't been run yet
      console.log('⚠️  Skipping test - run build first');
    }
  });

  it('should have main entry point in dist', () => {
    const indexJs = join(distDir, 'index.js');
    const indexDts = join(distDir, 'index.d.ts');
    
    if (existsSync(distDir)) {
      assert.equal(existsSync(indexJs), true, 'index.js should exist');
      assert.equal(existsSync(indexDts), true, 'index.d.ts should exist');
    } else {
      console.log('⚠️  Skipping test - run build first');
    }
  });

  it('should have all source files compiled', () => {
    if (!existsSync(distDir)) {
      console.log('⚠️  Skipping test - run build first');
      return;
    }

    const expectedFiles = [
      'index.js',
      'index.d.ts',
      'types.js',
      'types.d.ts',
      'errors.js',
      'errors.d.ts',
      'config.js',
      'config.d.ts',
      'hana-query-client.js',
      'hana-query-client.d.ts',
      'response-helpers.js',
      'response-helpers.d.ts'
    ];

    expectedFiles.forEach(file => {
      const filePath = join(distDir, file);
      assert.equal(existsSync(filePath), true, `${file} should exist in dist/`);
    });
  });

  it('should have examples directory compiled', () => {
    if (!existsSync(distDir)) {
      console.log('⚠️  Skipping test - run build first');
      return;
    }

    const examplesDir = join(distDir, 'examples');
    
    if (existsSync(examplesDir)) {
      assert.equal(statSync(examplesDir).isDirectory(), true);
      
      const expectedExampleFiles = [
        'basic-usage.js',
        'basic-usage.d.ts',
        'advanced-usage.js',
        'advanced-usage.d.ts',
        'error-handling.js',
        'error-handling.d.ts'
      ];

      expectedExampleFiles.forEach(file => {
        const filePath = join(examplesDir, file);
        assert.equal(existsSync(filePath), true, `examples/${file} should exist`);
      });
    }
  });

  it('should have source maps if configured', () => {
    if (!existsSync(distDir)) {
      console.log('⚠️  Skipping test - run build first');
      return;
    }

    // Check for source map files
    const files = readdirSync(distDir);
    const sourceMapFiles = files.filter(file => file.endsWith('.js.map'));
    
    // We expect source maps to be generated
    assert.equal(sourceMapFiles.length > 0, true, 'Should have source map files');
  });

  it('should not include test files in build output', () => {
    if (!existsSync(distDir)) {
      console.log('⚠️  Skipping test - run build first');
      return;
    }

    const files = readdirSync(distDir, { recursive: true });
    const testFiles = files.filter(file => 
      typeof file === 'string' && file.includes('.test.')
    );
    
    assert.equal(testFiles.length, 0, 'Test files should not be included in build output');
  });

  it('should preserve directory structure', () => {
    if (!existsSync(distDir)) {
      console.log('⚠️  Skipping test - run build first');
      return;
    }

    // Check that examples are in their own subdirectory
    const examplesDir = join(distDir, 'examples');
    
    // Should either exist or be excluded, but if it exists it should be a directory
    if (existsSync(examplesDir)) {
      assert.equal(statSync(examplesDir).isDirectory(), true);
    }
  });
});

describe('Build Configuration Validation', () => {
  it('should have tsconfig.build.json file', () => {
    const tsconfigBuild = join(process.cwd(), 'tsconfig.build.json');
    assert.equal(existsSync(tsconfigBuild), true, 'tsconfig.build.json should exist');
  });

  it('should have proper build script in package.json', async () => {
    const packageJsonPath = join(process.cwd(), 'package.json');
    assert.equal(existsSync(packageJsonPath), true, 'package.json should exist');
    
    const packageJson = JSON.parse(await import('node:fs').then(fs => 
      fs.readFileSync(packageJsonPath, 'utf-8')
    ));
    
    assert.equal(typeof packageJson.scripts.build, 'string', 'build script should be defined');
    assert.equal(packageJson.scripts.build.includes('tsc'), true, 'build script should use TypeScript compiler');
  });

  it('should have correct main and types fields for compiled output', async () => {
    const packageJsonPath = join(process.cwd(), 'package.json');
    const packageJson = JSON.parse(await import('node:fs').then(fs => 
      fs.readFileSync(packageJsonPath, 'utf-8')
    ));
    
    // After updating package.json in task 3, these should point to dist/
    if (packageJson.main && packageJson.main.startsWith('./dist/')) {
      assert.equal(packageJson.main, './dist/index.js', 'main should point to compiled output');
      assert.equal(packageJson.types, './dist/index.d.ts', 'types should point to declaration file');
    } else {
      console.log('⚠️  Package.json not yet updated for build output');
    }
  });
});