import { FileInfo, ImportInfo, ComponentInfo } from '@/types/file-manifest';

/**
 * Parse a JavaScript/JSX file to extract imports, exports, and component info
 */
export function parseJavaScriptFile(content: string, filePath: string): Partial<FileInfo> {
  const imports = extractImports(content);
  const exports = extractExports(content);
  const componentInfo = extractComponentInfo(content, filePath);
  const fileType = determineFileType(filePath, content);
  
  return {
    imports,
    exports,
    componentInfo,
    type: fileType,
  };
}

/**
 * Extract import statements from file content
 */
function extractImports(content: string): ImportInfo[] {
  const imports: ImportInfo[] = [];
  
  // Match import statements
  const importRegex = /import\s+(?:(.+?)\s+from\s+)?['"](.+?)['"]/g;
  const matches = content.matchAll(importRegex);
  
  for (const match of matches) {
    const [, importClause, source] = match;
    const importInfo: ImportInfo = {
      source,
      imports: [],
      isLocal: source.startsWith('./') || source.startsWith('../') || source.startsWith('@/'),
    };
    
    if (importClause) {
      // Handle default import
      const defaultMatch = importClause.match(/^(\w+)(?:,|$)/);
      if (defaultMatch) {
        importInfo.defaultImport = defaultMatch[1];
      }
      
      // Handle named imports
      const namedMatch = importClause.match(/\{([^}]+)\}/);
      if (namedMatch) {
        importInfo.imports = namedMatch[1]
          .split(',')
          .map(imp => imp.trim())
          .map(imp => imp.split(/\s+as\s+/)[0].trim());
      }
    }
    
    imports.push(importInfo);
  }
  
  return imports;
}

/**
 * Extract export statements from file content
 */
function extractExports(content: string): string[] {
  const exports: string[] = [];
  
  // Match default export
  if (/export\s+default\s+/m.test(content)) {
    // Try to find the name of the default export
    const defaultExportMatch = content.match(/export\s+default\s+(?:function\s+)?(\w+)/);
    if (defaultExportMatch) {
      exports.push(`default:${defaultExportMatch[1]}`);
    } else {
      exports.push('default');
    }
  }
  
  // Match named exports
  const namedExportRegex = /export\s+(?:const|let|var|function|class)\s+(\w+)/g;
  const namedMatches = content.matchAll(namedExportRegex);
  
  for (const match of namedMatches) {
    exports.push(match[1]);
  }
  
  // Match export { ... } statements
  const exportBlockRegex = /export\s+\{([^}]+)\}/g;
  const blockMatches = content.matchAll(exportBlockRegex);
  
  for (const match of blockMatches) {
    const names = match[1]
      .split(',')
      .map(exp => exp.trim())
      .map(exp => exp.split(/\s+as\s+/)[0].trim());
    exports.push(...names);
  }
  
  return exports;
}

/**
 * Extract React component information
 */
function extractComponentInfo(content: string, filePath: string): ComponentInfo | undefined {
  // Check if this is likely a React component
  const hasJSX = /<[A-Z]\w*|<[a-z]+\s+[^>]*\/?>/.test(content);
  if (!hasJSX && !content.includes('React')) return undefined;
  
  // Try to find component name
  let componentName = '';
  
  // Check for function component
  const funcComponentMatch = content.match(/(?:export\s+)?(?:default\s+)?function\s+([A-Z]\w*)\s*\(/);
  if (funcComponentMatch) {
    componentName = funcComponentMatch[1];
  } else {
    // Check for arrow function component
    const arrowComponentMatch = content.match(/(?:export\s+)?(?:default\s+)?(?:const|let)\s+([A-Z]\w*)\s*=\s*(?:\([^)]*\)|[^=])*=>/);
    if (arrowComponentMatch) {
      componentName = arrowComponentMatch[1];
    }
  }
  
  // If no component name found, try to get from filename
  if (!componentName) {
    const fileName = filePath.split('/').pop()?.replace(/\.(jsx?|tsx?)$/, '');
    if (fileName && /^[A-Z]/.test(fileName)) {
      componentName = fileName;
    }
  }
  
  if (!componentName) return undefined;
  
  // Extract hooks used
  const hooks: string[] = [];
  const hookRegex = /use[A-Z]\w*/g;
  const hookMatches = content.matchAll(hookRegex);
  for (const match of hookMatches) {
    if (!hooks.includes(match[0])) {
      hooks.push(match[0]);
    }
  }
  
  // Check if component has state
  const hasState = hooks.includes('useState') || hooks.includes('useReducer');
  
  // Extract child components (rough approximation)
  const childComponents: string[] = [];
  const componentRegex = /<([A-Z]\w*)[^>]*(?:\/?>|>)/g;
  const componentMatches = content.matchAll(componentRegex);
  
  for (const match of componentMatches) {
    const comp = match[1];
    if (!childComponents.includes(comp) && comp !== componentName) {
      childComponents.push(comp);
    }
  }
  
  return {
    name: componentName,
    hooks,
    hasState,
    childComponents,
  };
}

/**
 * Determine file type based on path and content
 */
function determineFileType(
  filePath: string,
  content: string
): FileInfo['type'] {
  const fileName = filePath.split('/').pop()?.toLowerCase() || '';
  const dirPath = filePath.toLowerCase();
  
  // Style files
  if (fileName.endsWith('.css')) return 'style';
  
  // Config files
  if (fileName.includes('config') || 
      fileName === 'vite.config.js' ||
      fileName === 'tailwind.config.js' ||
      fileName === 'postcss.config.js') {
    return 'config';
  }
  
  // Hook files
  if (dirPath.includes('/hooks/') || fileName.startsWith('use')) {
    return 'hook';
  }
  
  // Context files
  if (dirPath.includes('/context/') || fileName.includes('context')) {
    return 'context';
  }
  
  // Layout components
  if (fileName.includes('layout') || content.includes('children')) {
    return 'layout';
  }
  
  // Page components (in pages directory or have routing)
  if (dirPath.includes('/pages/') || 
      content.includes('useRouter') ||
      content.includes('useParams')) {
    return 'page';
  }
  
  // Utility files
  if (dirPath.includes('/utils/') || 
      dirPath.includes('/lib/') ||
      !content.includes('export default')) {
    return 'utility';
  }
  
  // Default to component
  return 'component';
}

/**
 * Build component dependency tree
 */
export function buildComponentTree(files: Record<string, FileInfo>) {
  const tree: Record<string, {
    file: string;
    imports: string[];
    importedBy: string[];
    type: 'page' | 'layout' | 'component';
  }> = {};
  
  // First pass: collect all components
  for (const [path, fileInfo] of Object.entries(files)) {
    if (fileInfo.componentInfo) {
      const componentName = fileInfo.componentInfo.name;
      tree[componentName] = {
        file: path,
        imports: [],
        importedBy: [],
        type: fileInfo.type === 'page' ? 'page' : 
              fileInfo.type === 'layout' ? 'layout' : 'component',
      };
    }
  }
  
  // Second pass: build relationships
  for (const [path, fileInfo] of Object.entries(files)) {
    if (fileInfo.componentInfo && fileInfo.imports) {
      const componentName = fileInfo.componentInfo.name;
      
      // Find imported components
      for (const imp of fileInfo.imports) {
        if (imp.isLocal && imp.defaultImport) {
          // Check if this import is a component we know about
          if (tree[imp.defaultImport]) {
            tree[componentName].imports.push(imp.defaultImport);
            tree[imp.defaultImport].importedBy.push(componentName);
          }
        }
      }
    }
  }
  
  return tree;
}