import { SymbolTable, ImportMap, ProjectContext, ExportMetadata } from '@scandiumsys/owstra-types';
import { BaseIndexer } from './indexers/base-indexer.js';
import { BaseResolver } from './resolvers/base-resolver.js';

export interface CallSite {
  filePath: string;
  argPositions: Array<{ row: number; column: number }>;
}

export class ProjectContextManager implements ProjectContext {
  public symbols: SymbolTable = {};
  public imports: Record<string, ImportMap> = {};
  public callSites: Record<string, CallSite[]> = {};
  
  private indexers: Map<string, BaseIndexer> = new Map();
  private resolvers: Map<string, BaseResolver> = new Map();
  private workspaceRoot: string;

  constructor(workspaceRoot: string) {
    this.workspaceRoot = workspaceRoot;
  }

  public getIndexer(language: string): BaseIndexer | undefined {
    return this.indexers.get(language);
  }

  public registerIndexer(indexer: BaseIndexer) {
    this.indexers.set(indexer.language, indexer);
  }

  public registerResolver(resolver: BaseResolver) {
    this.resolvers.set(resolver.language, resolver);
  }

  public addExports(language: string, exports: ExportMetadata[]) {
    for (const exp of exports) {
      if (!this.symbols[exp.name]) {
        this.symbols[exp.name] = [];
      }
      this.symbols[exp.name].push(exp);
    }
  }

  public addImports(filePath: string, imports: ImportMap) {
    this.imports[filePath] = imports;
  }

  public addCallSite(funcName: string, filePath: string, argPositions: Array<{ row: number; column: number }>) {
    if (!this.callSites[funcName]) {
        this.callSites[funcName] = [];
    }
    this.callSites[funcName].push({ filePath, argPositions });
  }

  /**
   * Resolves a local variable name in a file to its actual source definition.
   */
  public resolveDefinition(localName: string, filePath: string, language: string): ExportMetadata | null {
    const fileImports = this.imports[filePath];
    if (!fileImports || !fileImports[localName]) {
      // Not an imported symbol, might be local or global - but for cross-file we look for imports
      return null;
    }

    const sourcePath = fileImports[localName];
    const resolver = this.resolvers.get(language);
    if (!resolver) return null;

    const absoluteSourcePath = resolver.resolveImport(sourcePath, filePath, this.workspaceRoot);
    if (!absoluteSourcePath) return null;

    // Now find the symbol in the source path
    const potentialSymbols = this.symbols[localName]; // This is a bit simplified; needs to handle 'import { x as y }'
    if (!potentialSymbols) return null;

    return potentialSymbols.find(s => s.filePath === absoluteSourcePath) || null;
  }
}
