"use strict";
/**
 * Enhanced Performance Generator
 *
 * Generates comprehensive performance optimization configurations from enhanced schema.
 * Handles:
 * - Frontend optimization (code splitting, lazy loading, bundle budgets)
 * - Backend optimization (caching, connection pooling, query optimization)
 * - CDN configuration (Cloudflare, CloudFront, Fastly)
 * - Database optimization (read replicas, sharding, indexing)
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnhancedPerformanceGenerator = void 0;
const path_1 = __importDefault(require("path"));
class EnhancedPerformanceGenerator {
    id = 'enhanced-performance';
    name = 'Enhanced Performance Generator';
    description = 'Generates comprehensive performance optimization configurations from enhanced schema';
    generate(context) {
        const { workflow, outputDirectory } = context;
        const files = [];
        if (!workflow.performance) {
            return { files: [] };
        }
        const performance = workflow.performance;
        // Find backend and frontend components
        const backendComponent = Object.entries(workflow.stack).find(([_, c]) => c.type === 'backend');
        const frontendComponent = Object.entries(workflow.stack).find(([_, c]) => c.type === 'frontend');
        // Generate frontend performance optimizations
        if (frontendComponent && performance.frontend) {
            const [componentName] = frontendComponent;
            files.push(...this.generateFrontendPerformance(componentName, performance.frontend, outputDirectory));
        }
        // Generate backend performance optimizations
        if (backendComponent && performance.backend) {
            const [componentName] = backendComponent;
            files.push(...this.generateBackendPerformance(componentName, performance.backend, outputDirectory));
        }
        // Generate CDN configuration
        if (performance.cdn) {
            files.push(this.generateCDNConfig(performance.cdn, outputDirectory));
        }
        // Generate database optimization
        if (backendComponent && performance.database) {
            const [componentName] = backendComponent;
            files.push(...this.generateDatabaseOptimization(componentName, performance.database, outputDirectory));
        }
        return { files };
    }
    // ========================================
    // Frontend Performance Optimization
    // ========================================
    generateFrontendPerformance(componentName, frontend, outputDirectory) {
        const files = [];
        // Vite/Webpack configuration for performance
        files.push(this.generateBundlerConfig(componentName, frontend, outputDirectory));
        // Code splitting utilities
        if (frontend.code_splitting) {
            files.push(this.generateCodeSplittingUtils(componentName, frontend.code_splitting, outputDirectory));
        }
        // Lazy loading utilities
        if (frontend.lazy_loading) {
            files.push(this.generateLazyLoadingUtils(componentName, outputDirectory));
        }
        // Bundle analysis script
        if (frontend.bundle_budget) {
            files.push(this.generateBundleAnalysis(componentName, frontend.bundle_budget, outputDirectory));
        }
        return files;
    }
    generateBundlerConfig(componentName, frontend, outputDirectory) {
        const content = `/**
 * Vite Performance Configuration
 *
 * Optimizes bundle size and load times.
 * Generated from enhanced performance schema.
 */

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// Performance configuration
export const performanceConfig = {
  codeSplitting: '${frontend.code_splitting || 'route_based'}',
  lazyLoading: ${frontend.lazy_loading || false},
  treeShaking: ${frontend.tree_shaking !== false},
  bundleBudget: ${JSON.stringify(frontend.bundle_budget || {}, null, 2)},
};

export default defineConfig({
  plugins: [react()],

  build: {
    // Tree shaking
    minify: 'terser',
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true,
      },
    },

    // Code splitting
    rollupOptions: {
      output: {
        ${frontend.code_splitting === 'route_based' ? `
        // Route-based code splitting
        manualChunks(id) {
          // Vendor chunks
          if (id.includes('node_modules')) {
            if (id.includes('react') || id.includes('react-dom')) {
              return 'vendor-react';
            }
            if (id.includes('@tanstack') || id.includes('react-query')) {
              return 'vendor-query';
            }
            return 'vendor';
          }

          // Route-based chunks (automatically handled by React Router)
        },
        ` : frontend.code_splitting === 'component_based' ? `
        // Component-based code splitting
        manualChunks(id) {
          // Vendor chunks
          if (id.includes('node_modules')) {
            return 'vendor';
          }

          // Component library chunks
          if (id.includes('/components/')) {
            const componentMatch = id.match(/components\\/([^\\/]+)/);
            if (componentMatch) {
              return \`component-\${componentMatch[1]}\`;
            }
          }
        },
        ` : `
        // Manual code splitting (configure in your code)
        `}

        // Asset optimization
        assetFileNames: 'assets/[name]-[hash][extname]',
        chunkFileNames: 'chunks/[name]-[hash].js',
        entryFileNames: 'entry/[name]-[hash].js',
      },
    },

    // Chunk size warnings
    chunkSizeWarningLimit: ${this.parseBudgetSize(frontend.bundle_budget?.max_initial || '500kb')},
  },

  // Dependency optimization
  optimizeDeps: {
    include: ['react', 'react-dom'],
    ${frontend.lazy_loading ? `
    // Exclude lazy-loaded dependencies
    exclude: ['@heavy-lib'],
    ` : ''}
  },
});

/**
 * Bundle size analyzer (run: npm run build && npm run analyze)
 */
export function analyzeBundleSize() {
  // Use vite-bundle-visualizer or rollup-plugin-visualizer
  console.log('Bundle analysis enabled. Check stats.html after build.');
}
`;
        return {
            path: path_1.default.join(outputDirectory, componentName, 'vite.performance.config.ts'),
            content,
        };
    }
    parseBudgetSize(size) {
        const match = size.match(/^(\d+)(kb|mb)?$/i);
        if (!match)
            return 500;
        const value = parseInt(match[1], 10);
        const unit = match[2]?.toLowerCase();
        if (unit === 'mb')
            return value * 1024;
        return value;
    }
    generateCodeSplittingUtils(componentName, strategy, outputDirectory) {
        const content = `/**
 * Code Splitting Utilities
 *
 * Strategy: ${strategy}
 * Provides utilities for lazy loading components and routes.
 */

import { lazy, Suspense, ComponentType } from 'react';

/**
 * Lazy load a component with automatic retry on failure
 */
export function lazyWithRetry<T extends ComponentType<any>>(
  componentImport: () => Promise<{ default: T }>
): React.LazyExoticComponent<T> {
  return lazy(() =>
    componentImport().catch((error) => {
      // Retry once after a delay
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(componentImport());
        }, 1000);
      });
    })
  );
}

/**
 * Lazy load with preload support
 */
export function lazyWithPreload<T extends ComponentType<any>>(
  componentImport: () => Promise<{ default: T }>
) {
  const LazyComponent = lazy(componentImport);

  return {
    Component: LazyComponent,
    preload: componentImport,
  };
}

/**
 * Loading fallback component
 */
export function LoadingFallback({ message = 'Loading...' }: { message?: string }) {
  return (
    <div className="loading-fallback">
      <div className="spinner" />
      <p>{message}</p>
    </div>
  );
}

/**
 * Error boundary for lazy-loaded components
 */
export class LazyErrorBoundary extends React.Component<
  { children: React.ReactNode },
  { hasError: boolean }
> {
  state = { hasError: false };

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    console.error('Lazy loading error:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <div>Failed to load component. Please refresh the page.</div>;
    }

    return this.props.children;
  }
}

${strategy === 'route_based' ? `
/**
 * Route-based code splitting example
 */
export const routes = [
  {
    path: '/',
    component: lazyWithRetry(() => import('./pages/Home')),
  },
  {
    path: '/dashboard',
    component: lazyWithRetry(() => import('./pages/Dashboard')),
    preload: () => import('./pages/Dashboard'), // Preload on hover
  },
  {
    path: '/settings',
    component: lazyWithRetry(() => import('./pages/Settings')),
  },
];
` : strategy === 'component_based' ? `
/**
 * Component-based code splitting example
 */
export const HeavyChart = lazyWithPreload(() => import('./components/HeavyChart'));
export const DataTable = lazyWithPreload(() => import('./components/DataTable'));
export const ImageEditor = lazyWithPreload(() => import('./components/ImageEditor'));
` : ''}
`;
        return {
            path: path_1.default.join(outputDirectory, componentName, 'src/utils/code-splitting.tsx'),
            content,
        };
    }
    generateLazyLoadingUtils(componentName, outputDirectory) {
        const content = `/**
 * Lazy Loading Utilities
 *
 * Provides intersection observer-based lazy loading for images and components.
 */

import { useEffect, useRef, useState } from 'react';

/**
 * Lazy load images with intersection observer
 */
export function useLazyImage(src: string) {
  const [imageSrc, setImageSrc] = useState<string | null>(null);
  const [isLoaded, setIsLoaded] = useState(false);
  const imgRef = useRef<HTMLImageElement>(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            setImageSrc(src);
            observer.disconnect();
          }
        });
      },
      { rootMargin: '50px' }
    );

    if (imgRef.current) {
      observer.observe(imgRef.current);
    }

    return () => observer.disconnect();
  }, [src]);

  return { imgRef, imageSrc, isLoaded, onLoad: () => setIsLoaded(true) };
}

/**
 * LazyImage component
 */
export function LazyImage({
  src,
  alt,
  placeholder = '/placeholder.png',
  ...props
}: React.ImgHTMLAttributes<HTMLImageElement> & { placeholder?: string }) {
  const { imgRef, imageSrc, isLoaded, onLoad } = useLazyImage(src || '');

  return (
    <img
      ref={imgRef}
      src={imageSrc || placeholder}
      alt={alt}
      onLoad={onLoad}
      style={{ opacity: isLoaded ? 1 : 0.5, transition: 'opacity 0.3s' }}
      {...props}
    />
  );
}

/**
 * Lazy load components when they enter viewport
 */
export function useLazyComponent() {
  const [shouldRender, setShouldRender] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            setShouldRender(true);
            observer.disconnect();
          }
        });
      },
      { rootMargin: '100px' }
    );

    if (containerRef.current) {
      observer.observe(containerRef.current);
    }

    return () => observer.disconnect();
  }, []);

  return { containerRef, shouldRender };
}

/**
 * Preload critical resources
 */
export function preloadResource(url: string, as: 'script' | 'style' | 'image' | 'font') {
  const link = document.createElement('link');
  link.rel = 'preload';
  link.href = url;
  link.as = as;

  if (as === 'font') {
    link.crossOrigin = 'anonymous';
  }

  document.head.appendChild(link);
}

/**
 * Prefetch routes for faster navigation
 */
export function prefetchRoute(routePath: string) {
  const link = document.createElement('link');
  link.rel = 'prefetch';
  link.href = routePath;
  document.head.appendChild(link);
}
`;
        return {
            path: path_1.default.join(outputDirectory, componentName, 'src/utils/lazy-loading.tsx'),
            content,
        };
    }
    generateBundleAnalysis(componentName, budget, outputDirectory) {
        const content = `/**
 * Bundle Size Analysis and Budget Enforcement
 *
 * Budget: ${JSON.stringify(budget, null, 2)}
 */

import { promises as fs } from 'fs';
import path from 'path';

export const bundleBudget = ${JSON.stringify(budget, null, 2)};

/**
 * Parse size string to bytes
 */
function parseSize(size: string): number {
  const match = size.match(/^(\\d+)(kb|mb)?$/i);
  if (!match) throw new Error(\`Invalid size format: \${size}\`);

  const value = parseInt(match[1], 10);
  const unit = match[2]?.toLowerCase();

  if (unit === 'mb') return value * 1024 * 1024;
  if (unit === 'kb') return value * 1024;
  return value;
}

/**
 * Analyze bundle size and enforce budget
 */
export async function analyzeBundleSize() {
  const distPath = path.join(process.cwd(), 'dist');

  try {
    const files = await fs.readdir(distPath, { recursive: true });

    let totalSize = 0;
    let initialSize = 0;
    const fileDetails: Array<{ file: string; size: number }> = [];

    for (const file of files) {
      const filePath = path.join(distPath, String(file));
      const stats = await fs.stat(filePath);

      if (stats.isFile()) {
        const size = stats.size;
        totalSize += size;

        // Initial bundle (entry files)
        if (file.toString().includes('entry') || file.toString().includes('index')) {
          initialSize += size;
        }

        fileDetails.push({
          file: String(file),
          size,
        });
      }
    }

    // Sort by size
    fileDetails.sort((a, b) => b.size - a.size);

    // Report
    console.log('\\n📦 Bundle Size Analysis\\n');
    console.log('Largest files:');
    fileDetails.slice(0, 10).forEach(({ file, size }) => {
      console.log(\`  \${file}: \${formatSize(size)}\`);
    });

    console.log(\`\\nTotal bundle size: \${formatSize(totalSize)}\`);
    console.log(\`Initial bundle size: \${formatSize(initialSize)}\`);

    // Check budget
    const budgetViolations: string[] = [];

    if (bundleBudget.max_initial) {
      const maxInitial = parseSize(bundleBudget.max_initial);
      if (initialSize > maxInitial) {
        budgetViolations.push(
          \`Initial bundle (\${formatSize(initialSize)}) exceeds budget (\${bundleBudget.max_initial})\`
        );
      }
    }

    if (bundleBudget.max_total) {
      const maxTotal = parseSize(bundleBudget.max_total);
      if (totalSize > maxTotal) {
        budgetViolations.push(
          \`Total bundle (\${formatSize(totalSize)}) exceeds budget (\${bundleBudget.max_total})\`
        );
      }
    }

    if (budgetViolations.length > 0) {
      console.error('\\n❌ Bundle Budget Violations:\\n');
      budgetViolations.forEach(violation => console.error(\`  • \${violation}\`));
      process.exit(1);
    } else {
      console.log('\\n✅ Bundle within budget!\\n');
    }
  } catch (error) {
    console.error('Error analyzing bundle:', error);
    process.exit(1);
  }
}

function formatSize(bytes: number): string {
  if (bytes >= 1024 * 1024) {
    return \`\${(bytes / (1024 * 1024)).toFixed(2)} MB\`;
  }
  if (bytes >= 1024) {
    return \`\${(bytes / 1024).toFixed(2)} KB\`;
  }
  return \`\${bytes} bytes\`;
}

// Run if executed directly
if (require.main === module) {
  analyzeBundleSize();
}
`;
        return {
            path: path_1.default.join(outputDirectory, componentName, 'scripts/analyze-bundle.ts'),
            content,
        };
    }
    // ========================================
    // Backend Performance Optimization
    // ========================================
    generateBackendPerformance(componentName, backend, outputDirectory) {
        const files = [];
        // Caching configuration
        if (backend.caching) {
            files.push(this.generateCachingConfig(componentName, backend.caching, outputDirectory));
        }
        // Connection pooling
        if (backend.connection_pooling) {
            files.push(this.generateConnectionPooling(componentName, backend.connection_pooling, outputDirectory));
        }
        // Query optimization utilities
        if (backend.query_optimization) {
            files.push(this.generateQueryOptimization(componentName, outputDirectory));
        }
        return files;
    }
    generateCachingConfig(componentName, caching, outputDirectory) {
        const isRedis = caching.strategy === 'redis';
        const isMemcached = caching.strategy === 'memcached';
        const _isInMemory = caching.strategy === 'in_memory';
        const content = `/**
 * Caching Configuration
 *
 * Strategy: ${caching.strategy}
 * TTL: ${caching.ttl || 3600}s
 * Generated from enhanced performance schema.
 */

${isRedis ? `
import { createClient } from 'redis';

const client = createClient({
  url: process.env.REDIS_URL || 'redis://localhost:6379',
});

client.on('error', (err) => console.error('Redis Client Error', err));

await client.connect();
` : isMemcached ? `
import Memcached from 'memcached';

const client = new Memcached(process.env.MEMCACHED_URL || 'localhost:11211');
` : `
// In-memory cache (simple Map-based)
const cache = new Map<string, { value: any; expiry: number }>();
`}

// Cache configuration
export const cacheConfig = {
  strategy: '${caching.strategy}',
  ttl: ${caching.ttl || 3600},
  cacheKeys: ${JSON.stringify(caching.cache_keys || [], null, 2)},
};

/**
 * Get value from cache
 */
export async function getCache<T = any>(key: string): Promise<T | null> {
  ${isRedis ? `
  const value = await client.get(key);
  return value ? JSON.parse(value) : null;
  ` : isMemcached ? `
  return new Promise((resolve) => {
    client.get(key, (err, data) => {
      if (err || !data) return resolve(null);
      resolve(JSON.parse(data as string));
    });
  });
  ` : `
  const cached = cache.get(key);
  if (!cached) return null;

  if (Date.now() > cached.expiry) {
    cache.delete(key);
    return null;
  }

  return cached.value;
  `}
}

/**
 * Set value in cache
 */
export async function setCache(key: string, value: any, ttl?: number): Promise<void> {
  const expirySeconds = ttl || cacheConfig.ttl;

  ${isRedis ? `
  await client.setEx(key, expirySeconds, JSON.stringify(value));
  ` : isMemcached ? `
  return new Promise((resolve, reject) => {
    client.set(key, JSON.stringify(value), expirySeconds, (err) => {
      if (err) return reject(err);
      resolve();
    });
  });
  ` : `
  cache.set(key, {
    value,
    expiry: Date.now() + expirySeconds * 1000,
  });
  `}
}

/**
 * Delete value from cache
 */
export async function deleteCache(key: string): Promise<void> {
  ${isRedis ? `
  await client.del(key);
  ` : isMemcached ? `
  return new Promise((resolve, reject) => {
    client.del(key, (err) => {
      if (err) return reject(err);
      resolve();
    });
  });
  ` : `
  cache.delete(key);
  `}
}

/**
 * Clear all cache
 */
export async function clearCache(): Promise<void> {
  ${isRedis ? `
  await client.flushAll();
  ` : isMemcached ? `
  return new Promise((resolve, reject) => {
    client.flush((err) => {
      if (err) return reject(err);
      resolve();
    });
  });
  ` : `
  cache.clear();
  `}
}

/**
 * Cache decorator for functions
 */
export function cached(ttl?: number) {
  return function (
    target: any,
    propertyName: string,
    descriptor: PropertyDescriptor
  ) {
    const originalMethod = descriptor.value;

    descriptor.value = async function (...args: any[]) {
      const cacheKey = \`\${propertyName}:\${JSON.stringify(args)}\`;

      // Check cache
      const cached = await getCache(cacheKey);
      if (cached !== null) {
        return cached;
      }

      // Execute and cache
      const result = await originalMethod.apply(this, args);
      await setCache(cacheKey, result, ttl);

      return result;
    };

    return descriptor;
  };
}
`;
        return {
            path: path_1.default.join(outputDirectory, componentName, 'src/config/caching.ts'),
            content,
        };
    }
    generateConnectionPooling(componentName, pooling, outputDirectory) {
        const content = `/**
 * Database Connection Pooling Configuration
 *
 * Pool size: ${pooling.min}-${pooling.max}
 * Idle timeout: ${pooling.idle_timeout || 30000}ms
 * Generated from enhanced performance schema.
 */

import { Pool } from 'pg'; // PostgreSQL example

// Connection pool configuration
export const poolConfig = {
  min: ${pooling.min},
  max: ${pooling.max},
  idleTimeoutMillis: ${pooling.idle_timeout || 30000},
  connectionTimeoutMillis: 2000,
};

// Create connection pool
export const pool = new Pool({
  host: process.env.DB_HOST || 'localhost',
  port: parseInt(process.env.DB_PORT || '5432', 10),
  database: process.env.DB_NAME || 'app_db',
  user: process.env.DB_USER || 'postgres',
  password: process.env.DB_PASSWORD || 'password',
  ...poolConfig,
});

// Pool event handlers
pool.on('connect', (client) => {
  console.log('New client connected to pool');
});

pool.on('error', (err, client) => {
  console.error('Unexpected error on idle client', err);
  process.exit(-1);
});

pool.on('remove', (client) => {
  console.log('Client removed from pool');
});

/**
 * Query with automatic connection management
 */
export async function query(text: string, params?: any[]) {
  const start = Date.now();
  const res = await pool.query(text, params);
  const duration = Date.now() - start;

  if (duration > 1000) {
    console.warn(\`Slow query (\${duration}ms): \${text}\`);
  }

  return res;
}

/**
 * Transaction helper
 */
export async function transaction<T>(
  callback: (client: any) => Promise<T>
): Promise<T> {
  const client = await pool.connect();

  try {
    await client.query('BEGIN');
    const result = await callback(client);
    await client.query('COMMIT');
    return result;
  } catch (error) {
    await client.query('ROLLBACK');
    throw error;
  } finally {
    client.release();
  }
}

/**
 * Get pool statistics
 */
export function getPoolStats() {
  return {
    total: pool.totalCount,
    idle: pool.idleCount,
    waiting: pool.waitingCount,
  };
}

/**
 * Graceful shutdown
 */
export async function closePool() {
  await pool.end();
  console.log('Connection pool closed');
}

// Handle process termination
process.on('SIGTERM', closePool);
process.on('SIGINT', closePool);
`;
        return {
            path: path_1.default.join(outputDirectory, componentName, 'src/config/database-pool.ts'),
            content,
        };
    }
    generateQueryOptimization(componentName, outputDirectory) {
        const content = `/**
 * Query Optimization Utilities
 *
 * Provides tools for optimizing database queries.
 */

/**
 * Query performance monitoring
 */
export class QueryMonitor {
  private static slowQueries: Array<{ query: string; duration: number; timestamp: Date }> = [];
  private static readonly SLOW_QUERY_THRESHOLD = 1000; // ms

  static logQuery(query: string, duration: number) {
    if (duration > this.SLOW_QUERY_THRESHOLD) {
      this.slowQueries.push({
        query,
        duration,
        timestamp: new Date(),
      });

      console.warn(\`⚠️  Slow query (\${duration}ms): \${query.substring(0, 100)}...\`);
    }
  }

  static getSlowQueries() {
    return this.slowQueries;
  }

  static clearSlowQueries() {
    this.slowQueries = [];
  }
}

/**
 * Query builder with automatic optimization hints
 */
export class OptimizedQueryBuilder {
  private query: string = '';
  private params: any[] = [];

  select(fields: string | string[]) {
    const fieldList = Array.isArray(fields) ? fields.join(', ') : fields;
    this.query = \`SELECT \${fieldList}\`;
    return this;
  }

  from(table: string) {
    this.query += \` FROM \${table}\`;
    return this;
  }

  where(condition: string, ...params: any[]) {
    this.query += \` WHERE \${condition}\`;
    this.params.push(...params);
    return this;
  }

  join(table: string, condition: string) {
    this.query += \` JOIN \${table} ON \${condition}\`;
    return this;
  }

  orderBy(field: string, direction: 'ASC' | 'DESC' = 'ASC') {
    this.query += \` ORDER BY \${field} \${direction}\`;
    return this;
  }

  limit(count: number) {
    this.query += \` LIMIT \${count}\`;
    return this;
  }

  offset(count: number) {
    this.query += \` OFFSET \${count}\`;
    return this;
  }

  /**
   * Use index hint for query optimization
   */
  useIndex(indexName: string) {
    this.query += \` USE INDEX (\${indexName})\`;
    return this;
  }

  build() {
    return {
      text: this.query,
      values: this.params,
    };
  }
}

/**
 * Batch query executor for reducing round trips
 */
export async function executeBatch<T>(
  queries: Array<{ text: string; values?: any[] }>,
  pool: any
): Promise<T[]> {
  const client = await pool.connect();

  try {
    const results: T[] = [];

    for (const query of queries) {
      const result = await client.query(query.text, query.values);
      results.push(result.rows);
    }

    return results;
  } finally {
    client.release();
  }
}

/**
 * Cursor-based pagination for large datasets
 */
export async function* paginateWithCursor<T>(
  baseQuery: string,
  cursorField: string,
  pageSize: number = 100,
  pool: any
): AsyncGenerator<T[], void, unknown> {
  let cursor: any = null;

  while (true) {
    const query = cursor
      ? \`\${baseQuery} WHERE \${cursorField} > $1 ORDER BY \${cursorField} LIMIT \${pageSize}\`
      : \`\${baseQuery} ORDER BY \${cursorField} LIMIT \${pageSize}\`;

    const params = cursor ? [cursor] : [];
    const result = await pool.query(query, params);

    if (result.rows.length === 0) break;

    yield result.rows;

    cursor = result.rows[result.rows.length - 1][cursorField];
  }
}
`;
        return {
            path: path_1.default.join(outputDirectory, componentName, 'src/utils/query-optimization.ts'),
            content,
        };
    }
    // ========================================
    // CDN Configuration
    // ========================================
    generateCDNConfig(cdn, outputDirectory) {
        const content = `/**
 * CDN Configuration
 *
 * Provider: ${cdn.provider}
 * Cache TTL: ${cdn.cache_ttl || 86400}s
 * Generated from enhanced performance schema.
 */

// CDN configuration
export const cdnConfig = {
  provider: '${cdn.provider}',
  assets: ${JSON.stringify(cdn.assets || ['*.js', '*.css', '*.png', '*.jpg', '*.svg'], null, 2)},
  cacheTTL: ${cdn.cache_ttl || 86400},
};

${cdn.provider === 'cloudflare' ? `
/**
 * Cloudflare cache control headers
 */
export function setCloudflareCacheHeaders(res: any) {
  // Cache for ${cdn.cache_ttl || 86400} seconds
  res.setHeader('Cache-Control', 'public, max-age=${cdn.cache_ttl || 86400}');
  res.setHeader('CDN-Cache-Control', 'public, max-age=${cdn.cache_ttl || 86400}');

  // Cloudflare-specific headers
  res.setHeader('CF-Cache-Tag', 'static-assets');
}

/**
 * Purge Cloudflare cache
 */
export async function purgeCloudflarCache(files?: string[]) {
  const response = await fetch(
    \`https://api.cloudflare.com/client/v4/zones/\${process.env.CF_ZONE_ID}/purge_cache\`,
    {
      method: 'POST',
      headers: {
        'Authorization': \`Bearer \${process.env.CF_API_TOKEN}\`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        files: files || cdnConfig.assets,
      }),
    }
  );

  return response.json();
}
` : cdn.provider === 'cloudfront' ? `
/**
 * CloudFront cache control headers
 */
export function setCloudFrontCacheHeaders(res: any) {
  res.setHeader('Cache-Control', 'public, max-age=${cdn.cache_ttl || 86400}');
}

/**
 * Invalidate CloudFront cache
 */
export async function invalidateCloudFrontCache(paths: string[]) {
  const AWS = require('aws-sdk');
  const cloudfront = new AWS.CloudFront();

  const params = {
    DistributionId: process.env.CF_DISTRIBUTION_ID,
    InvalidationBatch: {
      CallerReference: Date.now().toString(),
      Paths: {
        Quantity: paths.length,
        Items: paths,
      },
    },
  };

  return cloudfront.createInvalidation(params).promise();
}
` : cdn.provider === 'fastly' ? `
/**
 * Fastly cache control headers
 */
export function setFastlyCacheHeaders(res: any) {
  res.setHeader('Cache-Control', 'public, max-age=${cdn.cache_ttl || 86400}');
  res.setHeader('Surrogate-Control', 'max-age=${cdn.cache_ttl || 86400}');
  res.setHeader('Surrogate-Key', 'static-assets');
}

/**
 * Purge Fastly cache
 */
export async function purgeFastlyCache(surrogateKeys: string[]) {
  const responses = [];

  for (const key of surrogateKeys) {
    const response = await fetch(
      \`https://api.fastly.com/service/\${process.env.FASTLY_SERVICE_ID}/purge/\${key}\`,
      {
        method: 'POST',
        headers: {
          'Fastly-Key': process.env.FASTLY_API_KEY || '',
          'Accept': 'application/json',
        },
      }
    );
    responses.push(await response.json());
  }

  return responses;
}
` : ''}

/**
 * Get CDN asset URL
 */
export function getCDNUrl(assetPath: string): string {
  const cdnBase = process.env.CDN_URL || '';
  return \`\${cdnBase}\${assetPath}\`;
}
`;
        return {
            path: path_1.default.join(outputDirectory, 'cdn.config.ts'),
            content,
        };
    }
    // ========================================
    // Database Optimization
    // ========================================
    generateDatabaseOptimization(componentName, database, outputDirectory) {
        const files = [];
        // Read replica configuration
        if (database.read_replicas && database.read_replicas > 0) {
            files.push(this.generateReadReplicaConfig(componentName, database.read_replicas, outputDirectory));
        }
        // Sharding configuration
        if (database.sharding) {
            files.push(this.generateShardingConfig(componentName, database.sharding, outputDirectory));
        }
        // Indexing utilities
        if (database.indexing_strategy) {
            files.push(this.generateIndexingUtils(componentName, database.indexing_strategy, outputDirectory));
        }
        return files;
    }
    generateReadReplicaConfig(componentName, replicaCount, outputDirectory) {
        const content = `/**
 * Read Replica Configuration
 *
 * Number of replicas: ${replicaCount}
 * Load balances read queries across replicas for improved performance.
 */

import { Pool } from 'pg';

// Primary database (for writes)
export const primaryPool = new Pool({
  host: process.env.DB_PRIMARY_HOST || 'localhost',
  port: parseInt(process.env.DB_PORT || '5432', 10),
  database: process.env.DB_NAME || 'app_db',
  user: process.env.DB_USER || 'postgres',
  password: process.env.DB_PASSWORD || 'password',
  max: 20,
});

// Read replicas (for reads)
const replicaPools = [
${Array.from({ length: replicaCount }, (_, i) => `
  new Pool({
    host: process.env.DB_REPLICA_${i + 1}_HOST || 'localhost',
    port: parseInt(process.env.DB_PORT || '5432', 10),
    database: process.env.DB_NAME || 'app_db',
    user: process.env.DB_USER || 'postgres',
    password: process.env.DB_PASSWORD || 'password',
    max: 20,
  }),
`).join('')}];

let currentReplicaIndex = 0;

/**
 * Get next read replica (round-robin)
 */
function getReadReplica(): Pool {
  const replica = replicaPools[currentReplicaIndex];
  currentReplicaIndex = (currentReplicaIndex + 1) % replicaPools.length;
  return replica;
}

/**
 * Execute read query on replica
 */
export async function readQuery(text: string, params?: any[]) {
  const replica = getReadReplica();
  return replica.query(text, params);
}

/**
 * Execute write query on primary
 */
export async function writeQuery(text: string, params?: any[]) {
  return primaryPool.query(text, params);
}

/**
 * Smart query router (automatically route based on query type)
 */
export async function query(text: string, params?: any[]) {
  const isWrite = /^(INSERT|UPDATE|DELETE|CREATE|ALTER|DROP)/i.test(text.trim());

  if (isWrite) {
    return writeQuery(text, params);
  } else {
    return readQuery(text, params);
  }
}

/**
 * Close all connections
 */
export async function closeAllPools() {
  await primaryPool.end();
  await Promise.all(replicaPools.map(pool => pool.end()));
}
`;
        return {
            path: path_1.default.join(outputDirectory, componentName, 'src/config/read-replicas.ts'),
            content,
        };
    }
    generateShardingConfig(componentName, sharding, outputDirectory) {
        const content = `/**
 * Database Sharding Configuration
 *
 * Strategy: ${sharding.strategy}
 * Shard count: ${sharding.shard_count || 4}
 * Generated from enhanced performance schema.
 */

import { Pool } from 'pg';
import crypto from 'crypto';

// Shard configuration
export const shardingConfig = {
  strategy: '${sharding.strategy}',
  shardCount: ${sharding.shard_count || 4},
};

// Create connection pools for each shard
const shardPools: Pool[] = [];

for (let i = 0; i < shardingConfig.shardCount; i++) {
  shardPools.push(
    new Pool({
      host: process.env[\`DB_SHARD_\${i + 1}_HOST\`] || 'localhost',
      port: parseInt(process.env.DB_PORT || '5432', 10),
      database: process.env[\`DB_SHARD_\${i + 1}_NAME\`] || \`app_db_shard_\${i + 1}\`,
      user: process.env.DB_USER || 'postgres',
      password: process.env.DB_PASSWORD || 'password',
      max: 20,
    })
  );
}

${sharding.strategy === 'by_tenant' ? `
/**
 * Get shard by tenant ID
 */
export function getShardByTenant(tenantId: string): Pool {
  const hash = crypto.createHash('md5').update(tenantId).digest('hex');
  const shardIndex = parseInt(hash.substring(0, 8), 16) % shardingConfig.shardCount;
  return shardPools[shardIndex];
}

/**
 * Query by tenant
 */
export async function queryByTenant(tenantId: string, text: string, params?: any[]) {
  const shard = getShardByTenant(tenantId);
  return shard.query(text, params);
}
` : sharding.strategy === 'by_date' ? `
/**
 * Get shard by date
 */
export function getShardByDate(date: Date): Pool {
  const year = date.getFullYear();
  const month = date.getMonth();
  const shardIndex = ((year * 12) + month) % shardingConfig.shardCount;
  return shardPools[shardIndex];
}

/**
 * Query by date range
 */
export async function queryByDateRange(startDate: Date, endDate: Date, text: string, params?: any[]) {
  // Determine which shards to query
  const shardsToQuery = new Set<Pool>();
  const current = new Date(startDate);

  while (current <= endDate) {
    shardsToQuery.add(getShardByDate(current));
    current.setMonth(current.getMonth() + 1);
  }

  // Query all relevant shards and merge results
  const results = await Promise.all(
    Array.from(shardsToQuery).map(shard => shard.query(text, params))
  );

  return results.flatMap(r => r.rows);
}
` : `
/**
 * Get shard by hash
 */
export function getShardByHash(key: string): Pool {
  const hash = crypto.createHash('md5').update(key).digest('hex');
  const shardIndex = parseInt(hash.substring(0, 8), 16) % shardingConfig.shardCount;
  return shardPools[shardIndex];
}

/**
 * Query by shard key
 */
export async function queryByShard(shardKey: string, text: string, params?: any[]) {
  const shard = getShardByHash(shardKey);
  return shard.query(text, params);
}

/**
 * Query all shards (for global queries)
 */
export async function queryAllShards(text: string, params?: any[]) {
  const results = await Promise.all(
    shardPools.map(shard => shard.query(text, params))
  );

  return results.flatMap(r => r.rows);
}
`}

/**
 * Close all shard connections
 */
export async function closeAllShards() {
  await Promise.all(shardPools.map(pool => pool.end()));
}
`;
        return {
            path: path_1.default.join(outputDirectory, componentName, 'src/config/sharding.ts'),
            content,
        };
    }
    generateIndexingUtils(componentName, strategy, outputDirectory) {
        const content = `/**
 * Database Indexing Utilities
 *
 * Strategy: ${strategy}
 * ${strategy === 'auto' ? 'Automatically suggests indexes based on query patterns.' : 'Manual index management tools.'}
 */

${strategy === 'auto' ? `
/**
 * Analyze query patterns and suggest indexes
 */
export class IndexSuggester {
  private queryLog: Map<string, number> = new Map();

  logQuery(query: string) {
    const normalized = this.normalizeQuery(query);
    this.queryLog.set(normalized, (this.queryLog.get(normalized) || 0) + 1);
  }

  private normalizeQuery(query: string): string {
    // Remove specific values, keep structure
    return query
      .replace(/\\$\\d+/g, '$N')
      .replace(/'[^']*'/g, "'...'")
      .replace(/\\d+/g, 'N')
      .trim();
  }

  suggestIndexes(): string[] {
    const suggestions: string[] = [];

    for (const [query, count] of this.queryLog.entries()) {
      if (count < 10) continue; // Only suggest for frequently run queries

      // Extract table and where clauses
      const tableMatch = query.match(/FROM\\s+(\\w+)/i);
      const whereMatch = query.match(/WHERE\\s+([\\w.]+)\\s*[=><!]/i);

      if (tableMatch && whereMatch) {
        const table = tableMatch[1];
        const column = whereMatch[1].replace(/^\\w+\\./, ''); // Remove table prefix
        suggestions.push(\`CREATE INDEX idx_\${table}_\${column} ON \${table}(\${column});\`);
      }
    }

    return [...new Set(suggestions)]; // Deduplicate
  }

  getQueryStats() {
    return Array.from(this.queryLog.entries())
      .sort((a, b) => b[1] - a[1])
      .slice(0, 10);
  }
}

export const indexSuggester = new IndexSuggester();
` : `
/**
 * Manual index management
 */
export const indexDefinitions = [
  // User indexes
  { table: 'users', columns: ['email'], name: 'idx_users_email' },
  { table: 'users', columns: ['created_at'], name: 'idx_users_created_at' },

  // Add your indexes here
];

/**
 * Generate CREATE INDEX statements
 */
export function generateIndexSQL(): string[] {
  return indexDefinitions.map(({ table, columns, name }) => {
    return \`CREATE INDEX IF NOT EXISTS \${name} ON \${table}(\${columns.join(', ')});\`;
  });
}

/**
 * Analyze index usage
 */
export async function analyzeIndexUsage(pool: any) {
  const query = \`
    SELECT
      schemaname,
      tablename,
      indexname,
      idx_scan as scans,
      idx_tup_read as tuples_read,
      idx_tup_fetch as tuples_fetched
    FROM pg_stat_user_indexes
    WHERE idx_scan = 0
    ORDER BY schemaname, tablename;
  \`;

  const result = await pool.query(query);

  console.log('\\n📊 Unused Indexes:\\n');
  result.rows.forEach((row: any) => {
    console.log(\`  \${row.schemaname}.\${row.tablename}.\${row.indexname}\`);
  });
}
`}
`;
        return {
            path: path_1.default.join(outputDirectory, componentName, 'src/utils/indexing.ts'),
            content,
        };
    }
}
exports.EnhancedPerformanceGenerator = EnhancedPerformanceGenerator;
//# sourceMappingURL=enhanced-performance-generator.js.map