/**
 * C# language provider.
 *
 * C# uses named imports (using directives), modifier-based export detection,
 * and an implements-split MRO strategy for multiple interface implementation.
 * Interface names follow the I-prefix convention (e.g., IDisposable).
 */

import { SupportedLanguages } from 'gitnexus-shared';
import { createClassExtractor } from '../class-extractors/generic.js';
import { csharpClassConfig } from '../class-extractors/configs/csharp.js';
import { defineLanguage } from '../language-provider.js';
import { typeConfig as csharpConfig } from '../type-extractors/csharp.js';
import { csharpExportChecker } from '../export-detection.js';
import { createImportResolver } from '../import-resolvers/resolver-factory.js';
import { csharpImportConfig } from '../import-resolvers/configs/csharp.js';
import { CSHARP_QUERIES } from '../tree-sitter-queries.js';
import type { AstFrameworkPatternConfig } from '../language-provider.js';
import { createCallExtractor } from '../call-extractors/generic.js';
import { csharpCallConfig } from '../call-extractors/configs/csharp.js';
import { createFieldExtractor } from '../field-extractors/generic.js';
import { csharpConfig as csharpFieldConfig } from '../field-extractors/configs/csharp.js';
import { createMethodExtractor } from '../method-extractors/generic.js';
import { csharpMethodConfig } from '../method-extractors/configs/csharp.js';
import { createVariableExtractor } from '../variable-extractors/generic.js';
import { csharpVariableConfig } from '../variable-extractors/configs/csharp.js';
import {
  emitCsharpScopeCaptures,
  interpretCsharpImport,
  interpretCsharpTypeBinding,
  csharpBindingScopeFor,
  csharpImportOwningScope,
  csharpMergeBindings,
  csharpReceiverBinding,
  csharpArityCompatibility,
  resolveCsharpImportTarget,
} from './csharp/index.js';

const BUILT_INS: ReadonlySet<string> = new Set([
  'Console',
  'WriteLine',
  'ReadLine',
  'Write',
  'Task',
  'Run',
  'Wait',
  'WhenAll',
  'WhenAny',
  'FromResult',
  'Delay',
  'ContinueWith',
  'ConfigureAwait',
  'GetAwaiter',
  'GetResult',
  'ToString',
  'GetType',
  'Equals',
  'GetHashCode',
  'ReferenceEquals',
  'Add',
  'Remove',
  'Contains',
  'Clear',
  'Count',
  'Any',
  'All',
  'Where',
  'Select',
  'SelectMany',
  'OrderBy',
  'OrderByDescending',
  'GroupBy',
  'First',
  'FirstOrDefault',
  'Single',
  'SingleOrDefault',
  'Last',
  'LastOrDefault',
  'ToList',
  'ToArray',
  'ToDictionary',
  'AsEnumerable',
  'AsQueryable',
  'Aggregate',
  'Sum',
  'Average',
  'Min',
  'Max',
  'Distinct',
  'Skip',
  'Take',
  'String',
  'Format',
  'IsNullOrEmpty',
  'IsNullOrWhiteSpace',
  'Concat',
  'Join',
  'Trim',
  'TrimStart',
  'TrimEnd',
  'Split',
  'Replace',
  'StartsWith',
  'EndsWith',
  'Convert',
  'ToInt32',
  'ToDouble',
  'ToBoolean',
  'ToByte',
  'Math',
  'Abs',
  'Ceiling',
  'Floor',
  'Round',
  'Pow',
  'Sqrt',
  'Dispose',
  'Close',
  'TryParse',
  'Parse',
  'AddRange',
  'RemoveAt',
  'RemoveAll',
  'FindAll',
  'Exists',
  'TrueForAll',
  'ContainsKey',
  'TryGetValue',
  'AddOrUpdate',
  'Throw',
  'ThrowIfNull',
]);

export const csharpProvider = defineLanguage({
  id: SupportedLanguages.CSharp,
  extensions: ['.cs'],
  entryPointPatterns: [
    /^(Get|Post|Put|Delete|Patch)/,
    /Action$/,
    /^On[A-Z]/,
    /Async$/,
    /^Configure$/,
    /^ConfigureServices$/,
    /^Handle$/,
    /^Execute$/,
    /^Invoke$/,
    /^Map[A-Z]/,
    /Service$/,
    /^Seed/,
  ],
  astFrameworkPatterns: [
    {
      framework: 'aspnet',
      entryPointMultiplier: 3.2,
      reason: 'aspnet-attribute',
      patterns: [
        '[ApiController]',
        '[HttpGet]',
        '[HttpPost]',
        '[HttpPut]',
        '[HttpDelete]',
        '[Route]',
        '[Authorize]',
        '[AllowAnonymous]',
      ],
    },
    {
      framework: 'signalr',
      entryPointMultiplier: 2.8,
      reason: 'signalr-attribute',
      patterns: ['[HubMethodName]', ': Hub', ': Hub<'],
    },
    {
      framework: 'blazor',
      entryPointMultiplier: 2.5,
      reason: 'blazor-attribute',
      patterns: ['@page', '[Parameter]', '@inject'],
    },
    {
      framework: 'efcore',
      entryPointMultiplier: 2.0,
      reason: 'efcore-pattern',
      patterns: ['DbContext', 'DbSet<', 'OnModelCreating'],
    },
  ] satisfies AstFrameworkPatternConfig[],
  treeSitterQueries: CSHARP_QUERIES,
  typeConfig: csharpConfig,
  exportChecker: csharpExportChecker,
  importResolver: createImportResolver(csharpImportConfig),
  mroStrategy: 'implements-split',
  callExtractor: createCallExtractor(csharpCallConfig),
  fieldExtractor: createFieldExtractor(csharpFieldConfig),
  methodExtractor: createMethodExtractor(csharpMethodConfig),
  variableExtractor: createVariableExtractor(csharpVariableConfig),
  classExtractor: createClassExtractor(csharpClassConfig),
  builtInNames: BUILT_INS,

  // ── RFC #909 Ring 3: scope-based resolution hooks (RFC §5) ──────────
  // C# is the second migration after Python. See ./csharp/index.ts for
  // the full per-hook rationale and the canonical capture vocabulary
  // in ./csharp/query.ts (CSHARP_SCOPE_QUERY constant).
  emitScopeCaptures: emitCsharpScopeCaptures,
  interpretImport: interpretCsharpImport,
  interpretTypeBinding: interpretCsharpTypeBinding,
  bindingScopeFor: csharpBindingScopeFor,
  importOwningScope: csharpImportOwningScope,
  mergeBindings: (_scope, bindings) => csharpMergeBindings(bindings),
  receiverBinding: csharpReceiverBinding,
  arityCompatibility: csharpArityCompatibility,
  resolveImportTarget: resolveCsharpImportTarget,
});
