/**
 * Base Parser Interface
 *
 * Abstract interface for language-specific code parsers.
 */

import path from 'path';
import type { FileEntities } from '../../graph/types.js';
import type { SupportedLanguage } from '../types.js';

/**
 * Abstract base class for language parsers
 */
export abstract class BaseLanguageParser {
  protected filePath: string;
  protected repoRoot: string;

  constructor(filePath: string, repoRoot?: string) {
    this.filePath = filePath;
    this.repoRoot = repoRoot ?? path.dirname(filePath);
  }

  /**
   * Parse the file and extract entities
   */
  abstract parse(): Promise<FileEntities>;

  /**
   * Get supported file extensions for this parser
   */
  abstract getSupportedExtensions(): string[];

  /**
   * Get the language this parser handles
   */
  abstract getLanguage(): SupportedLanguage;

  /**
   * Calculate module name from file path
   * e.g., /repo/src/utils/helpers.ts -> src.utils.helpers
   */
  protected calculateModuleName(): string {
    const relativePath = path.relative(this.repoRoot, this.filePath);
    const parsed = path.parse(relativePath);
    const dir = parsed.dir.replace(/[/\\]/g, '.');
    const name = parsed.name;

    // Handle index files
    if (name === 'index') {
      return dir || 'index';
    }

    return dir ? `${dir}.${name}` : name;
  }

  /**
   * Get the file extension
   */
  protected getExtension(): string {
    return path.extname(this.filePath).toLowerCase();
  }

  /**
   * Get the file name without extension
   */
  protected getFileName(): string {
    return path.basename(this.filePath);
  }

  /**
   * Calculate qualified name for an entity
   */
  protected qualifiedName(entityName: string, parentName?: string): string {
    const moduleName = this.calculateModuleName();
    if (parentName) {
      return `${moduleName}.${parentName}.${entityName}`;
    }
    return `${moduleName}.${entityName}`;
  }
}

/**
 * Parser constructor type for registry
 */
export type ParserConstructor = new (filePath: string, repoRoot?: string) => BaseLanguageParser;
