import { GraphQLQuery, GraphQLField } from "@graphql-lint/core";
import fs from "fs";
import path from "path";
import { glob } from "glob";

interface ClintAction {
  name: string;
  pattern: string; // clint.entity.method
  file: string;
  line: number;
}

export class ClintGraphQLExtractor {
  
  async extractFromPath(targetPath: string, actions: ClintAction[], includePatterns: string[], excludePatterns: string[]): Promise<void> {
    const stats = fs.statSync(targetPath);
    
    if (stats.isFile()) {
      if (targetPath.endsWith('actions.graphql')) {
        await this.extractFromFile(targetPath, actions);
      }
    } else if (stats.isDirectory()) {
      // Buscar por arquivos actions.graphql
      const files = await glob("**/actions.graphql", {
        cwd: targetPath,
        ignore: excludePatterns,
        absolute: true
      });
      
      for (const file of files) {
        await this.extractFromFile(file, actions);
      }
    }
  }

  async extractFromFile(filePath: string, actions: ClintAction[]): Promise<void> {
    try {
      const content = fs.readFileSync(filePath, 'utf-8');
      const extractedActions = this.parseActionsGraphQL(content, filePath);
      actions.push(...extractedActions);
    } catch (error) {
      console.warn(`⚠️  Erro ao ler arquivo ${filePath}:`, error);
    }
  }

  private parseActionsGraphQL(content: string, filePath: string): ClintAction[] {
    const actions: ClintAction[] = [];
    const lines = content.split('\n');
    
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];
      const lineNumber = i + 1;
      
      // Detectar definições de actions (padrão comum do Hasura)
      // Exemplo: action_name { ... }
      const actionMatch = line.match(/^\s*([a-z_]+)\s*\{/);
      if (actionMatch) {
        const actionName = actionMatch[1];
        const clintPattern = this.actionToClintPattern(actionName);
        
        actions.push({
          name: actionName,
          pattern: clintPattern,
          file: filePath,
          line: lineNumber
        });
      }
    }
    
    return actions;
  }

  /**
   * Converte nome de action do Hasura para padrão Clint
   * Exemplo: owner_get_name -> clint.owner.getName
   */
  actionToClintPattern(actionName: string): string {
    const parts = actionName.split('_');
    if (parts.length < 3) {
      return `clint.${actionName}`;
    }
    
    const [entity, action, ...details] = parts;
    const methodName = action + details.map(d => 
      d.charAt(0).toUpperCase() + d.slice(1)
    ).join('');
    
    return `clint.${entity}.${methodName}`;
  }

  /**
   * Converte padrão Clint para nome de action do Hasura
   * Exemplo: clint.owner.getName -> owner_get_name
   */
  clintPatternToAction(pattern: string): string {
    const match = pattern.match(/^clint\.([^.]+)\.([^.]+)$/);
    if (!match) {
      return pattern.replace('clint.', '');
    }
    
    const [, entity, method] = match;
    
    // Converter camelCase para snake_case
    const actionPart = method.replace(/([A-Z])/g, '_$1').toLowerCase();
    
    return `${entity}_${actionPart}`;
  }
}

export { ClintAction };
