#!/usr/bin/env tsx

/**
 * Updated smoke test for the blog with file examples
 * Tests: Build succeeds, key files exist, data is valid, file examples work
 */

import { execSync } from 'child_process';
import fs from 'fs';
import path from 'path';

console.log('🔍 Running updated smoke tests for mintel.me blog...\n');

let passed = 0;
let failed = 0;

async function test(name: string, fn: () => void | Promise<void>): Promise<void> {
  try {
    const result = fn();
    if (result instanceof Promise) {
      await result;
    }
    console.log(`✅ ${name}`);
    passed++;
  } catch (error) {
    console.log(`❌ ${name}`);
    if (error instanceof Error) {
      console.log(`   Error: ${error.message}`);
    }
    failed++;
  }
}

// Test 1: Check required files exist
test('Required files exist', () => {
  const requiredFiles = [
    'package.json',
    'astro.config.mjs',
    'tailwind.config.js',
    'src/pages/index.astro',
    'src/layouts/BaseLayout.astro',
    'src/data/blogPosts.ts',
    'src/styles/global.css'
  ];

  for (const file of requiredFiles) {
    if (!fs.existsSync(path.join(process.cwd(), file))) {
      throw new Error(`Missing file: ${file}`);
    }
  }
});

// Test 2: Validate blog posts data
test('Blog posts data is valid', () => {
  const blogPostsPath = path.join(process.cwd(), 'src/data/blogPosts.ts');
  const content = fs.readFileSync(blogPostsPath, 'utf8');
  
  if (!content.includes('export const blogPosts')) {
    throw new Error('blogPosts export not found');
  }
  
  const postsMatch = content.match(/\{[^}]+\}/g);
  if (!postsMatch || postsMatch.length === 0) {
    throw new Error('No posts found in blogPosts.ts');
  }
  
  const firstPost = postsMatch[0];
  const requiredFields = ['title', 'description', 'date', 'slug', 'tags'];
  
  for (const field of requiredFields) {
    if (!firstPost.includes(field)) {
      throw new Error(`First post missing required field: ${field}`);
    }
  }
});

// Test 3: Check Astro config
test('Astro configuration is valid', () => {
  const configPath = path.join(process.cwd(), 'astro.config.mjs');
  const content = fs.readFileSync(configPath, 'utf8');
  
  if (!content.includes('site:')) {
    throw new Error('site URL not configured');
  }
  
  if (!content.includes('react()')) {
    throw new Error('React integration not configured');
  }
});

// Test 4: Validate Tailwind config
test('Tailwind configuration is valid', () => {
  const configPath = path.join(process.cwd(), 'tailwind.config.js');
  const content = fs.readFileSync(configPath, 'utf8');
  
  if (!content.includes('content:')) {
    throw new Error('content paths not configured');
  }
  
  if (!content.includes('plugins:')) {
    throw new Error('plugins not configured');
  }
});

// Test 5: Check for syntax errors in key components
test('Key components have valid syntax', () => {
  const components = [
    'src/components/MediumCard.astro',
    'src/components/SearchBar.tsx',
    'src/components/ArticleBlockquote.tsx',
    'src/components/FileExample.astro',
    'src/components/FileExamplesList.astro'
  ];
  
  for (const component of components) {
    const componentPath = path.join(process.cwd(), component);
    if (fs.existsSync(componentPath)) {
      const content = fs.readFileSync(componentPath, 'utf8');
      
      // Basic syntax checks
      if (content.includes('import') && !content.includes('export') && !content.includes('---')) {
        throw new Error(`${component}: has imports but no exports`);
      }
      
      // Check for balanced braces
      const openBraces = (content.match(/{/g) || []).length;
      const closeBraces = (content.match(/}/g) || []).length;
      if (openBraces !== closeBraces) {
        throw new Error(`${component}: unbalanced braces`);
      }
    }
  }
});

// Test 6: Check global styles
test('Global styles include required classes', () => {
  const stylesPath = path.join(process.cwd(), 'src/styles/global.css');
  const content = fs.readFileSync(stylesPath, 'utf8');
  
  const requiredClasses = [
    '.container',
    '.highlighter-tag',
    '.post-card',
    '.article-content',
    '.search-box',
    '.file-example', // New file example classes
  ];
  
  for (const className of requiredClasses) {
    if (!content.includes(className)) {
      throw new Error(`Missing required class: ${className}`);
    }
  }
});

// Test 7: Verify package.json scripts
test('Package.json has required scripts', () => {
  const packagePath = path.join(process.cwd(), 'package.json');
  const content = fs.readFileSync(packagePath, 'utf8');
  
  const requiredScripts = ['dev', 'build', 'preview', 'test:smoke'];
  
  for (const script of requiredScripts) {
    if (!content.includes(`"${script}"`)) {
      throw new Error(`Missing script: ${script}`);
    }
  }
});

// Test 8: Check for single-page blog functionality
test('Single-page blog functionality exists', () => {
  const functionalityFiles = [
    'src/pages/index.astro',
    'src/components/SearchBar.tsx',
    'src/components/MediumCard.astro'
  ];
  
  for (const file of functionalityFiles) {
    const filePath = path.join(process.cwd(), file);
    if (!fs.existsSync(filePath)) {
      throw new Error(`Missing functionality file: ${file}`);
    }
  }
});

// Test 9: Check that all blog posts load in the home page
test('All blog posts load in home page', () => {
  const homePagePath = path.join(process.cwd(), 'src/pages/index.astro');
  const homeContent = fs.readFileSync(homePagePath, 'utf8');
  
  if (!homeContent.includes('import') || !homeContent.includes('blogPosts')) {
    throw new Error('Home page does not import blogPosts');
  }
  
  if (!homeContent.includes('allPosts.map') && !homeContent.includes('blogPosts.map')) {
    throw new Error('Home page does not render blog posts');
  }
  
  if (!homeContent.includes('MediumCard')) {
    throw new Error('MediumCard component not used in home page');
  }
});

// Test 10: Verify blog posts have all required fields
test('Blog posts have all required fields', () => {
  const blogPostsPath = path.join(process.cwd(), 'src/data/blogPosts.ts');
  const content = fs.readFileSync(blogPostsPath, 'utf8');
  
  const posts = content.match(/\{[^}]+\}/g) || [];
  
  if (posts.length === 0) {
    throw new Error('No posts found in blogPosts.ts');
  }
  
  const requiredFields = ['title', 'description', 'date', 'slug', 'tags'];
  
  posts.forEach((post, index) => {
    for (const field of requiredFields) {
      if (!post.includes(field)) {
        throw new Error(`Post ${index + 1} missing required field: ${field}`);
      }
    }
  });
});

// Test 11: Verify dynamic blog post routing exists
test('Dynamic blog post routing exists', () => {
  const blogDir = path.join(process.cwd(), 'src/pages/blog');
  const files = fs.readdirSync(blogDir);
  
  if (!files.includes('[slug].astro')) {
    throw new Error('Missing [slug].astro for dynamic blog post routing');
  }
  
  const slugPagePath = path.join(blogDir, '[slug].astro');
  const content = fs.readFileSync(slugPagePath, 'utf8');
  
  if (!content.includes('getStaticPaths')) {
    throw new Error('[slug].astro missing getStaticPaths function');
  }
  
  if (!content.includes('blogPosts')) {
    throw new Error('[slug].astro does not use blogPosts data');
  }
});

// Test 12: Verify home page has no navigation
test('Home page has no navigation links', () => {
  const homePagePath = path.join(process.cwd(), 'src/pages/index.astro');
  const content = fs.readFileSync(homePagePath, 'utf8');
  
  if (content.includes('href="/about"') || content.includes('href="/blog"')) {
    throw new Error('Home page contains navigation links');
  }
  
  if (content.includes('<nav') || content.includes('nav class')) {
    throw new Error('Home page contains navigation elements');
  }
});

// Test 13: Verify blog post pages use BaseLayout
test('Blog posts use BaseLayout', () => {
  const slugPagePath = path.join(process.cwd(), 'src/pages/blog/[slug].astro');
  const content = fs.readFileSync(slugPagePath, 'utf8');
  
  if (!content.includes('import BaseLayout')) {
    throw new Error('Slug page does not import BaseLayout');
  }
  
  if (content.includes('import BlogLayout')) {
    throw new Error('Slug page still imports BlogLayout which does not exist');
  }
});

// Test 14: Verify tag pages exist and are valid
test('Tag pages exist and are valid', () => {
  const tagPagePath = path.join(process.cwd(), 'src/pages/tags/[tag].astro');
  
  if (!fs.existsSync(tagPagePath)) {
    throw new Error('Tag page [tag].astro does not exist');
  }
  
  const content = fs.readFileSync(tagPagePath, 'utf8');
  
  if (!content.includes('import BaseLayout')) {
    throw new Error('Tag page does not import BaseLayout');
  }
  
  if (!content.includes('getStaticPaths')) {
    throw new Error('Tag page missing getStaticPaths function');
  }
  
  if (!content.includes('posts.map')) {
    throw new Error('Tag page does not render posts');
  }
});

// Test 15: Verify file examples functionality exists
test('File examples functionality exists', () => {
  const requiredFiles = [
    'src/data/fileExamples.ts',
    'src/components/FileExample.astro',
    'src/components/FileExamplesList.astro',
    'src/pages/api/download-zip.ts',
  ];
  
  for (const file of requiredFiles) {
    const filePath = path.join(process.cwd(), file);
    if (!fs.existsSync(filePath)) {
      throw new Error(`Missing file examples file: ${file}`);
    }
  }
});

// Test 16: Verify file examples data structure
test('File examples data is valid', () => {
  const fileExamplesPath = path.join(process.cwd(), 'src/data/fileExamples.ts');
  const content = fs.readFileSync(fileExamplesPath, 'utf8');
  
  if (!content.includes('export interface FileExample')) {
    throw new Error('FileExample interface not found');
  }
  
  if (!content.includes('export const sampleFileExamples')) {
    throw new Error('sampleFileExamples export not found');
  }
  
  if (!content.includes('FileExampleManager')) {
    throw new Error('FileExampleManager class not found');
  }
});

// Test 17: Verify blog template supports file examples
test('Blog template supports file examples', () => {
  const blogTemplatePath = path.join(process.cwd(), 'src/pages/blog/[slug].astro');
  const content = fs.readFileSync(blogTemplatePath, 'utf8');
  
  if (!content.includes('FileExamplesList')) {
    throw new Error('Blog template does not import FileExamplesList');
  }
  
  if (!content.includes('showFileExamples')) {
    throw new Error('Blog template does not have file examples logic');
  }
});

// Test 18: Verify API endpoint exists
test('Download API endpoint exists', () => {
  const apiPath = path.join(process.cwd(), 'src/pages/api/download-zip.ts');
  const content = fs.readFileSync(apiPath, 'utf8');
  
  if (!content.includes('export const POST')) {
    throw new Error('API endpoint missing POST handler');
  }
  
  if (!content.includes('export const GET')) {
    throw new Error('API endpoint missing GET handler');
  }
  
  if (!content.includes('FileExampleManager')) {
    throw new Error('API endpoint does not use FileExampleManager');
  }
});

// Test 19: Verify no syntax errors in Astro files
test('No syntax errors in Astro files', () => {
  const astroFiles = [
    'src/pages/index.astro',
    'src/pages/blog/[slug].astro',
    'src/pages/tags/[tag].astro',
    'src/layouts/BaseLayout.astro'
  ];
  
  for (const file of astroFiles) {
    const filePath = path.join(process.cwd(), file);
    if (!fs.existsSync(filePath)) {
      throw new Error(`File ${file} does not exist`);
    }
    
    const content = fs.readFileSync(filePath, 'utf8');
    
    // Check for balanced braces in script sections
    const scriptSections = content.match(/---[\s\S]*?---/g) || [];
    let totalOpenBraces = 0;
    let totalCloseBraces = 0;
    
    for (const section of scriptSections) {
      totalOpenBraces += (section.match(/{/g) || []).length;
      totalCloseBraces += (section.match(/}/g) || []).length;
    }
    
    if (totalOpenBraces !== totalCloseBraces) {
      throw new Error(`${file} has unbalanced braces in script section`);
    }
  }
});

// Test 20: Verify blogPosts.ts can be imported without errors
test('blogPosts.ts can be imported without errors', () => {
  const blogPostsPath = path.join(process.cwd(), 'src/data/blogPosts.ts');
  const content = fs.readFileSync(blogPostsPath, 'utf8');
  
  if (!content.includes('export const blogPosts')) {
    throw new Error('blogPosts.ts does not export blogPosts');
  }
  
  const openBraces = (content.match(/{/g) || []).length;
  const closeBraces = (content.match(/}/g) || []).length;
  if (openBraces !== closeBraces) {
    throw new Error('blogPosts.ts has unbalanced braces');
  }
});

// Test 21: Verify Astro build succeeds
test('Astro build succeeds without runtime errors', () => {
  try {
    execSync('npm run build', {
      cwd: process.cwd(),
      stdio: 'pipe',
      timeout: 60000
    });
  } catch (error: any) {
    const stderr = error.stderr?.toString() || '';
    const stdout = error.stdout?.toString() || '';
    const combined = stderr + stdout;
    
    if (combined.includes('children.trim is not a function')) {
      throw new Error('Build failed: children.trim error - component children issue');
    }
    
    if (combined.includes('is not a function')) {
      throw new Error(`Build failed with runtime error: ${combined.substring(0, 200)}`);
    }
    
    if (combined.includes('Build failed') && !combined.includes('warning')) {
      throw new Error(`Build failed: ${combined.substring(0, 300)}`);
    }
  }
});

// Test 22: Verify all components can be imported
test('All components can be imported without errors', () => {
  const components = [
    'src/components/MediumCard.astro',
    'src/components/SearchBar.tsx',
    'src/components/ArticleBlockquote.tsx',
    'src/components/ArticleHeading.tsx',
    'src/components/ArticleParagraph.tsx',
    'src/components/ArticleList.tsx',
    'src/components/Footer.tsx',
    'src/components/FileExample.astro',
    'src/components/FileExamplesList.astro'
  ];
  
  for (const component of components) {
    const componentPath = path.join(process.cwd(), component);
    if (!fs.existsSync(componentPath)) {
      throw new Error(`Component ${component} does not exist`);
    }
    
    const content = fs.readFileSync(componentPath, 'utf8');
    
    // Check for common issues
    if (content.includes('children.trim') && !content.includes('children?.trim')) {
      throw new Error(`${component}: uses children.trim without null check`);
    }
  }
});

// Test 23: Run comprehensive file examples tests
test('File examples data system works correctly', async () => {
  // Import and run the file examples tests
  const { runFileExamplesTests } = await import('../src/utils/test-file-examples.ts');
  await runFileExamplesTests();
});

// Test 24: Run blog post integration tests
test('Blog post and file examples integration works', async () => {
  // Import and run the integration tests
  const { testBlogPostIntegration } = await import('../src/utils/test-component-integration.ts');
  await testBlogPostIntegration();
});

// Summary
async function runAllTests() {
  // Run synchronous tests first
  const syncTests = [
    () => test('Required files exist', () => {
      const requiredFiles = [
        'package.json',
        'astro.config.mjs',
        'tailwind.config.js',
        'src/pages/index.astro',
        'src/layouts/BaseLayout.astro',
        'src/data/blogPosts.ts',
        'src/styles/global.css'
      ];

      for (const file of requiredFiles) {
        if (!fs.existsSync(path.join(process.cwd(), file))) {
          throw new Error(`Missing file: ${file}`);
        }
      }
    }),
    
    () => test('Blog posts data is valid', () => {
      const blogPostsPath = path.join(process.cwd(), 'src/data/blogPosts.ts');
      const content = fs.readFileSync(blogPostsPath, 'utf8');
      
      if (!content.includes('export const blogPosts')) {
        throw new Error('blogPosts export not found');
      }
      
      const postsMatch = content.match(/\{[^}]+\}/g);
      if (!postsMatch || postsMatch.length === 0) {
        throw new Error('No posts found in blogPosts.ts');
      }
      
      const firstPost = postsMatch[0];
      const requiredFields = ['title', 'description', 'date', 'slug', 'tags'];
      
      for (const field of requiredFields) {
        if (!firstPost.includes(field)) {
          throw new Error(`First post missing required field: ${field}`);
        }
      }
    }),
    
    () => test('Astro configuration is valid', () => {
      const configPath = path.join(process.cwd(), 'astro.config.mjs');
      const content = fs.readFileSync(configPath, 'utf8');
      
      if (!content.includes('site:')) {
        throw new Error('site URL not configured');
      }
      
      if (!content.includes('react()')) {
        throw new Error('React integration not configured');
      }
    }),
    
    () => test('Tailwind configuration is valid', () => {
      const configPath = path.join(process.cwd(), 'tailwind.config.js');
      const content = fs.readFileSync(configPath, 'utf8');
      
      if (!content.includes('content:')) {
        throw new Error('content paths not configured');
      }
      
      if (!content.includes('plugins:')) {
        throw new Error('plugins not configured');
      }
    }),
    
    () => test('Key components have valid syntax', () => {
      const components = [
        'src/components/MediumCard.astro',
        'src/components/SearchBar.tsx',
        'src/components/ArticleBlockquote.tsx',
        'src/components/FileExample.astro',
        'src/components/FileExamplesList.astro'
      ];
      
      for (const component of components) {
        const componentPath = path.join(process.cwd(), component);
        if (fs.existsSync(componentPath)) {
          const content = fs.readFileSync(componentPath, 'utf8');
          
          // Basic syntax checks
          if (content.includes('import') && !content.includes('export') && !content.includes('---')) {
            throw new Error(`${component}: has imports but no exports`);
          }
          
          // Check for balanced braces
          const openBraces = (content.match(/{/g) || []).length;
          const closeBraces = (content.match(/}/g) || []).length;
          if (openBraces !== closeBraces) {
            throw new Error(`${component}: unbalanced braces`);
          }
        }
      }
    }),
    
    () => test('Global styles include required classes', () => {
      const stylesPath = path.join(process.cwd(), 'src/styles/global.css');
      const content = fs.readFileSync(stylesPath, 'utf8');
      
      const requiredClasses = [
        '.container',
        '.highlighter-tag',
        '.post-card',
        '.article-content',
        '.search-box',
        '.file-example',
      ];
      
      for (const className of requiredClasses) {
        if (!content.includes(className)) {
          throw new Error(`Missing required class: ${className}`);
        }
      }
    }),
    
    () => test('Package.json has required scripts', () => {
      const packagePath = path.join(process.cwd(), 'package.json');
      const content = fs.readFileSync(packagePath, 'utf8');
      
      const requiredScripts = ['dev', 'build', 'preview', 'test:smoke'];
      
      for (const script of requiredScripts) {
        if (!content.includes(`"${script}"`)) {
          throw new Error(`Missing script: ${script}`);
        }
      }
    }),
    
    () => test('Single-page blog functionality exists', () => {
      const functionalityFiles = [
        'src/pages/index.astro',
        'src/components/SearchBar.tsx',
        'src/components/MediumCard.astro'
      ];
      
      for (const file of functionalityFiles) {
        const filePath = path.join(process.cwd(), file);
        if (!fs.existsSync(filePath)) {
          throw new Error(`Missing functionality file: ${file}`);
        }
      }
    }),
    
    () => test('All blog posts load in home page', () => {
      const homePagePath = path.join(process.cwd(), 'src/pages/index.astro');
      const homeContent = fs.readFileSync(homePagePath, 'utf8');
      
      if (!homeContent.includes('import') || !homeContent.includes('blogPosts')) {
        throw new Error('Home page does not import blogPosts');
      }
      
      if (!homeContent.includes('allPosts.map') && !homeContent.includes('blogPosts.map')) {
        throw new Error('Home page does not render blog posts');
      }
      
      if (!homeContent.includes('MediumCard')) {
        throw new Error('MediumCard component not used in home page');
      }
    }),
    
    () => test('Blog posts have all required fields', () => {
      const blogPostsPath = path.join(process.cwd(), 'src/data/blogPosts.ts');
      const content = fs.readFileSync(blogPostsPath, 'utf8');
      
      const posts = content.match(/\{[^}]+\}/g) || [];
      
      if (posts.length === 0) {
        throw new Error('No posts found in blogPosts.ts');
      }
      
      const requiredFields = ['title', 'description', 'date', 'slug', 'tags'];
      
      posts.forEach((post, index) => {
        for (const field of requiredFields) {
          if (!post.includes(field)) {
            throw new Error(`Post ${index + 1} missing required field: ${field}`);
          }
        }
      });
    }),
    
    () => test('Dynamic blog post routing exists', () => {
      const blogDir = path.join(process.cwd(), 'src/pages/blog');
      const files = fs.readdirSync(blogDir);
      
      if (!files.includes('[slug].astro')) {
        throw new Error('Missing [slug].astro for dynamic blog post routing');
      }
      
      const slugPagePath = path.join(blogDir, '[slug].astro');
      const content = fs.readFileSync(slugPagePath, 'utf8');
      
      if (!content.includes('getStaticPaths')) {
        throw new Error('[slug].astro missing getStaticPaths function');
      }
      
      if (!content.includes('blogPosts')) {
        throw new Error('[slug].astro does not use blogPosts data');
      }
    }),
    
    () => test('Home page has no navigation links', () => {
      const homePagePath = path.join(process.cwd(), 'src/pages/index.astro');
      const content = fs.readFileSync(homePagePath, 'utf8');
      
      if (content.includes('href="/about"') || content.includes('href="/blog"')) {
        throw new Error('Home page contains navigation links');
      }
      
      if (content.includes('<nav') || content.includes('nav class')) {
        throw new Error('Home page contains navigation elements');
      }
    }),
    
    () => test('Blog posts use BaseLayout', () => {
      const slugPagePath = path.join(process.cwd(), 'src/pages/blog/[slug].astro');
      const content = fs.readFileSync(slugPagePath, 'utf8');
      
      if (!content.includes('import BaseLayout')) {
        throw new Error('Slug page does not import BaseLayout');
      }
      
      if (content.includes('import BlogLayout')) {
        throw new Error('Slug page still imports BlogLayout which does not exist');
      }
    }),
    
    () => test('Tag pages exist and are valid', () => {
      const tagPagePath = path.join(process.cwd(), 'src/pages/tags/[tag].astro');
      
      if (!fs.existsSync(tagPagePath)) {
        throw new Error('Tag page [tag].astro does not exist');
      }
      
      const content = fs.readFileSync(tagPagePath, 'utf8');
      
      if (!content.includes('import BaseLayout')) {
        throw new Error('Tag page does not import BaseLayout');
      }
      
      if (!content.includes('getStaticPaths')) {
        throw new Error('Tag page missing getStaticPaths function');
      }
      
      if (!content.includes('posts.map')) {
        throw new Error('Tag page does not render posts');
      }
    }),
    
    () => test('File examples functionality exists', () => {
      const requiredFiles = [
        'src/data/fileExamples.ts',
        'src/components/FileExample.astro',
        'src/components/FileExamplesList.astro',
        'src/pages/api/download-zip.ts',
      ];
      
      for (const file of requiredFiles) {
        const filePath = path.join(process.cwd(), file);
        if (!fs.existsSync(filePath)) {
          throw new Error(`Missing file examples file: ${file}`);
        }
      }
    }),
    
    () => test('File examples data is valid', () => {
      const fileExamplesPath = path.join(process.cwd(), 'src/data/fileExamples.ts');
      const content = fs.readFileSync(fileExamplesPath, 'utf8');
      
      if (!content.includes('export interface FileExample')) {
        throw new Error('FileExample interface not found');
      }
      
      if (!content.includes('export const sampleFileExamples')) {
        throw new Error('sampleFileExamples export not found');
      }
      
      if (!content.includes('FileExampleManager')) {
        throw new Error('FileExampleManager class not found');
      }
    }),
    
    () => test('Blog template supports file examples', () => {
      const blogTemplatePath = path.join(process.cwd(), 'src/pages/blog/[slug].astro');
      const content = fs.readFileSync(blogTemplatePath, 'utf8');
      
      if (!content.includes('FileExamplesList')) {
        throw new Error('Blog template does not import FileExamplesList');
      }
      
      if (!content.includes('showFileExamples')) {
        throw new Error('Blog template does not have file examples logic');
      }
    }),
    
    () => test('Download API endpoint exists', () => {
      const apiPath = path.join(process.cwd(), 'src/pages/api/download-zip.ts');
      const content = fs.readFileSync(apiPath, 'utf8');

      if (!content.includes('export const POST')) {
        throw new Error('API endpoint missing POST handler');
      }

      if (!content.includes('export const GET')) {
        throw new Error('API endpoint missing GET handler');
      }

      if (!content.includes('FileExampleManager')) {
        throw new Error('API endpoint does not use FileExampleManager');
      }
    }),
    
    () => test('No syntax errors in Astro files', () => {
      const astroFiles = [
        'src/pages/index.astro',
        'src/pages/blog/[slug].astro',
        'src/pages/tags/[tag].astro',
        'src/layouts/BaseLayout.astro'
      ];
      
      for (const file of astroFiles) {
        const filePath = path.join(process.cwd(), file);
        if (!fs.existsSync(filePath)) {
          throw new Error(`File ${file} does not exist`);
        }
        
        const content = fs.readFileSync(filePath, 'utf8');
        
        // Check for balanced braces in script sections
        const scriptSections = content.match(/---[\s\S]*?---/g) || [];
        let totalOpenBraces = 0;
        let totalCloseBraces = 0;
        
        for (const section of scriptSections) {
          totalOpenBraces += (section.match(/{/g) || []).length;
          totalCloseBraces += (section.match(/}/g) || []).length;
        }
        
        if (totalOpenBraces !== totalCloseBraces) {
          throw new Error(`${file} has unbalanced braces in script section`);
        }
      }
    }),
    
    () => test('blogPosts.ts can be imported without errors', () => {
      const blogPostsPath = path.join(process.cwd(), 'src/data/blogPosts.ts');
      const content = fs.readFileSync(blogPostsPath, 'utf8');
      
      if (!content.includes('export const blogPosts')) {
        throw new Error('blogPosts.ts does not export blogPosts');
      }
      
      const openBraces = (content.match(/{/g) || []).length;
      const closeBraces = (content.match(/}/g) || []).length;
      if (openBraces !== closeBraces) {
        throw new Error('blogPosts.ts has unbalanced braces');
      }
    }),
    
    () => test('Astro build succeeds without runtime errors', () => {
      try {
        execSync('npm run build', {
          cwd: process.cwd(),
          stdio: 'pipe',
          timeout: 60000
        });
      } catch (error: any) {
        const stderr = error.stderr?.toString() || '';
        const stdout = error.stdout?.toString() || '';
        const combined = stderr + stdout;
        
        if (combined.includes('children.trim is not a function')) {
          throw new Error('Build failed: children.trim error - component children issue');
        }
        
        if (combined.includes('is not a function')) {
          throw new Error(`Build failed with runtime error: ${combined.substring(0, 200)}`);
        }
        
        if (combined.includes('Build failed') && !combined.includes('warning')) {
          throw new Error(`Build failed: ${combined.substring(0, 300)}`);
        }
      }
    }),
    
    () => test('All components can be imported without errors', () => {
      const components = [
        'src/components/MediumCard.astro',
        'src/components/SearchBar.tsx',
        'src/components/ArticleBlockquote.tsx',
        'src/components/ArticleHeading.tsx',
        'src/components/ArticleParagraph.tsx',
        'src/components/ArticleList.tsx',
        'src/components/Footer.tsx',
        'src/components/FileExample.astro',
        'src/components/FileExamplesList.astro'
      ];

      for (const component of components) {
        const componentPath = path.join(process.cwd(), component);
        if (!fs.existsSync(componentPath)) {
          throw new Error(`Component ${component} does not exist`);
        }

        const content = fs.readFileSync(componentPath, 'utf8');

        // Check for common issues
        if (content.includes('children.trim') && !content.includes('children?.trim')) {
          throw new Error(`${component}: uses children.trim without null check`);
        }
      }
    }),

    () => test('OG image API route exists', () => {
      const ogApiPath = path.join(process.cwd(), 'src/pages/api/og/[...slug].svg.ts');

      if (!fs.existsSync(ogApiPath)) {
        throw new Error('OG image API route does not exist');
      }

      const content = fs.readFileSync(ogApiPath, 'utf8');

      if (!content.includes('export async function getStaticPaths')) {
        throw new Error('OG API route missing getStaticPaths function');
      }

      if (!content.includes('export const GET')) {
        throw new Error('OG API route missing GET handler');
      }

      if (!content.includes('blogPosts')) {
        throw new Error('OG API route does not use blogPosts data');
      }
    }),

    () => test('OG images are generated in dist', () => {
      const ogDir = path.join(process.cwd(), 'dist/api/og');

      if (!fs.existsSync(ogDir)) {
        throw new Error('OG images directory does not exist in dist');
      }

      const files = fs.readdirSync(ogDir);
      const expectedFiles = ['home.svg', 'first-note.svg', 'debugging-tips.svg', 'architecture-patterns.svg', 'docker-deployment.svg', 'embed-demo.svg'];

      for (const expectedFile of expectedFiles) {
        if (!files.includes(expectedFile)) {
          throw new Error(`Missing OG image: ${expectedFile}`);
        }
      }
    }),

    () => test('OG images have correct content', () => {
      const ogDir = path.join(process.cwd(), 'dist/api/og');
      const homeOgPath = path.join(ogDir, 'home.svg');

      if (!fs.existsSync(homeOgPath)) {
        throw new Error('Home OG image does not exist');
      }

      const content = fs.readFileSync(homeOgPath, 'utf8');

      if (!content.includes('<svg')) {
        throw new Error('OG image is not valid SVG');
      }

      if (!content.includes('Marc Mintel')) {
        throw new Error('OG image does not contain expected title');
      }

      if (!content.includes('mintel.me')) {
        throw new Error('OG image does not contain site branding');
      }

      if (!content.includes('system-ui')) {
        throw new Error('OG image does not use system fonts');
      }
    }),

    () => test('BaseLayout uses OG images', () => {
      const baseLayoutPath = path.join(process.cwd(), 'src/layouts/BaseLayout.astro');
      const content = fs.readFileSync(baseLayoutPath, 'utf8');

      if (!content.includes('ogImage')) {
        throw new Error('BaseLayout does not set og:image meta tag');
      }

      if (!content.includes('twitterImage')) {
        throw new Error('BaseLayout does not set twitter:image meta tag');
      }

      if (!content.includes('/api/og/')) {
        throw new Error('BaseLayout does not use OG image API route');
      }
    }),
  ];

  // Run all sync tests
  for (const testFn of syncTests) {
    await testFn();
  }

  // Summary
  console.log('\n' + '='.repeat(50));
  console.log(`Tests passed: ${passed}`);
  console.log(`Tests failed: ${failed}`);
  console.log('='.repeat(50));

  if (failed === 0) {
    console.log('\n🎉 All updated smoke tests passed! Your blog with file examples is ready to use.');
    console.log('\nKey features verified:');
    console.log('  ✅ Single-page blog with search and filtering');
    console.log('  ✅ Dynamic blog post routing');
    console.log('  ✅ Tag filtering pages');
    console.log('  ✅ File examples with copy/download/zip functionality');
    console.log('  ✅ API endpoints for file downloads');
    console.log('  ✅ Comprehensive data and integration tests');
    console.log('\nTo start development:');
    console.log('  npm run dev');
    console.log('\nTo build for production:');
    console.log('  npm run build');
    process.exit(0);
  } else {
    console.log('\n❌ Some tests failed. Please check the errors above.');
    process.exit(1);
  }
}

runAllTests().catch(err => {
  console.error('Test runner failed:', err);
  process.exit(1);
});