// Copyright (c) 2026, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:collection';
import 'dart:io';

import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:collection/collection.dart';

import 'api_declaration.dart';
import 'api_summary_customizer.dart';
import 'api_type.dart';
import 'extensions.dart';

/// Traverses the public libraries of [packageName] within [context] to build
/// a canonical [ApiSummary] representation.
///
/// Filtering and discovery behaviors are customized using [customizer].
Future<ApiSummary> buildApiPackage(
  String packageName,
  AnalysisContext context,
  ApiSummaryCustomizer customizer,
) => _ApiBuilder(packageName, customizer).build(context);

/// Internal builder traversing analysis results to build structured API
/// summaries.
final class _ApiBuilder {
  final ApiSummaryCustomizer _customizer;
  final String _pkgName;

  final _immediateSubinterfaceCache =
      <LibraryElement, Map<ClassElement, Set<InterfaceElement>>>{};

  final _processedElements = <Element>{};
  final _pendingElements = Queue<Element>();
  final _libraryBuilders = <String, _ApiLibraryBuilder>{};
  final _elementToLibraries = <Element, List<LibraryElement>>{};

  _ApiBuilder(this._pkgName, this._customizer);

  Future<ApiSummary> build(AnalysisContext context) async {
    final publicApiLibraries = <LibraryElement>[];
    final topLevelPublicElements = <Element>{};
    final scanContext = ApiSummaryContext(
      packageName: _pkgName,
      analysisContext: context,
      publicApiLibraries: publicApiLibraries,
      topLevelPublicElements: topLevelPublicElements,
    );
    await _customizer.setupComplete(scanContext);

    await _scanPublicApiLibraries(
      context,
      topLevelPublicElements,
      publicApiLibraries,
    );
    await _customizer.initialScanComplete(scanContext);

    while (_pendingElements.isNotEmpty) {
      final element = _pendingElements.removeFirst();
      if (!_processedElements.add(element)) continue;

      final isReferenced = !(element.library?.uri.isIn(_pkgName) ?? false);

      final ApiDeclarationStatus status;
      if (topLevelPublicElements.contains(element)) {
        status = ApiDeclarationStatus.public;
      } else if (!isReferenced) {
        status = ApiDeclarationStatus.nonPublic;
      } else {
        status = ApiDeclarationStatus.referenced;
      }

      final showDetails = _customizer.shouldShowDetails(element, scanContext);
      if (!showDetails && !_customizer.includeReferencedTypes) continue;

      final libraries =
          _elementToLibraries[element] ??
          [if (element.library != null) element.library!];

      final apiElement = switch (element) {
        EnumElement() => _buildClass(
          element,
          includeMembers: showDetails,
          status: status,
        ),
        MixinElement() => _buildClass(
          element,
          includeMembers: showDetails,
          status: status,
        ),
        ClassElement() => _buildClass(
          element,
          includeMembers: showDetails,
          status: status,
        ),
        ExtensionElement() => _buildExtension(
          element,
          includeMembers: showDetails,
          status: status,
        ),
        ExtensionTypeElement() => _buildExtensionType(
          element,
          includeMembers: showDetails,
          status: status,
        ),
        TopLevelFunctionElement() => _buildExecutable(element, status: status),
        PropertyAccessorElement() => _buildExecutable(element, status: status),
        TypeAliasElement() => _buildTypeAlias(element, status: status),
        _ => null,
      };

      if (apiElement == null) {
        stderr.writeln(
          'Warning: Skipping unsupported top-level element "${element.name}" '
          '(${element.runtimeType})',
        );
        continue;
      }

      for (final library in libraries) {
        final builder = _libraryBuilders.putIfAbsent(
          library.uri.toString(),
          () => _ApiLibraryBuilder(
            library.uri.toString(),
            isPublicEntryPoint: library.uri.isInPublicLibOf(_pkgName),
          ),
        );
        switch (apiElement) {
          case ApiClass():
            switch (element) {
              case EnumElement():
                builder.enums.add(apiElement);
              case MixinElement():
                builder.mixins.add(apiElement);
              default:
                builder.classes.add(apiElement);
            }
          case ApiExtension():
            builder.extensions.add(apiElement);
          case ApiExtensionType():
            builder.extensionTypes.add(apiElement);
          case ApiExecutable():
            builder.functions.add(apiElement);
          case ApiTypeAlias():
            builder.typeAliases.add(apiElement);
        }
      }
    }

    final libraries = _libraryBuilders.values.map((e) => e.build()).toList();

    return ApiSummary(name: _pkgName, libraries: libraries);
  }

  Future<void> _scanPublicApiLibraries(
    AnalysisContext context,
    Set<Element> topLevelPublicElements,
    List<LibraryElement> publicApiLibraries,
  ) async {
    for (final file in context.contextRoot.analyzedFiles().sorted()) {
      if (!file.endsWith('.dart')) continue;
      final fileResult = context.currentSession.getFile(file);
      if (fileResult is! FileResult) continue;
      final uri = fileResult.uri;
      if (fileResult.isLibrary && uri.isInPublicLibOf(_pkgName)) {
        final resolvedLibraryResult = await context.currentSession
            .getResolvedLibrary(file);
        if (resolvedLibraryResult is! ResolvedLibraryResult) continue;
        final library = resolvedLibraryResult.element;
        final definedNames = library.exportNamespace.definedNames2;
        for (final key in definedNames.keys.sorted()) {
          final element = definedNames[key]!;
          topLevelPublicElements.add(element);
          (_elementToLibraries[element] ??= []).add(library);
          _maybeAddPending(element);
        }
        publicApiLibraries.add(library);
        _libraryBuilders.putIfAbsent(
          library.uri.toString(),
          () => _ApiLibraryBuilder(
            library.uri.toString(),
            isPublicEntryPoint: true,
          ),
        );
      }
    }
  }

  void _maybeAddPending(Element element) {
    if (_processedElements.contains(element)) return;
    _pendingElements.add(element);
  }

  bool _isNullable(NullabilitySuffix suffix) => switch (suffix) {
    NullabilitySuffix.none => false,
    NullabilitySuffix.question => true,
    NullabilitySuffix.star => throw UnsupportedError(
      'Legacy nullability (.star) is not supported.',
    ),
  };

  bool _isVisibleForTesting(Element element) =>
      element.nonSynthetic.metadata.hasVisibleForTesting;

  ApiType _describeType(DartType type) {
    final isNullable = _isNullable(type.nullabilitySuffix);
    switch (type) {
      case DynamicType():
        return const ApiDynamicType();
      case FunctionType(
        :final returnType,
        :final typeParameters,
        :final formalParameters,
      ):
        final apiParameters = <ApiParameter>[];
        for (final p in formalParameters) {
          apiParameters.add(
            ApiParameter(
              name: p.name ?? '',
              type: _describeType(p.type),
              isRequired: p.isRequired,
              isNamed: p.isNamed,
              isOptionalPositional: p.isOptionalPositional,
              isDeprecated: p.isDeprecated,
            ),
          );
        }

        return ApiFunctionType(
          returnType: _describeType(returnType),
          typeParameters: _extractTypeParameters(typeParameters),
          parameters: apiParameters,
          isNullable: isNullable,
        );
      case InterfaceType(:final element, :final typeArguments):
        _maybeAddPending(element);
        return ApiInterfaceType(
          name: element.name ?? '',
          libraryUri: element.library.uri.toString(),
          typeArguments: typeArguments.map(_describeType).toList(),
          isNullable: isNullable,
        );
      case RecordType(:final positionalFields, :final namedFields):
        return ApiRecordType(
          positionalFields: positionalFields
              .map((f) => _describeType(f.type))
              .toList(),
          namedFields: namedFields
              .sortedBy((f) => f.name)
              .map(
                (f) => ApiRecordNamedField(
                  name: f.name,
                  type: _describeType(f.type),
                ),
              )
              .toList(),
          isNullable: isNullable,
        );
      case TypeParameterType(:final element):
        return ApiTypeParameterType(
          name: element.name ?? '',
          isNullable: isNullable,
        );
      case NeverType():
        return ApiInterfaceType(
          name: 'Never',
          libraryUri: 'dart:core',
          typeArguments: const [],
          isNullable: isNullable,
        );
      case VoidType():
        return const ApiVoidType();
      // When analyzing a workspace with mid-edit syntax errors or unresolved
      // identifiers (e.g., unimported annotations), the analyzer produces an
      // InvalidType. We gracefully fall back to dynamic to avoid crashing.
      case InvalidType():
        return const ApiDynamicType();
      case dynamic(:final runtimeType):
        stderr.writeln(
          'Warning: Encountered unexpected DartType "$runtimeType", '
          'falling back to dynamic',
        );
        return const ApiDynamicType();
    }
  }

  Map<String, ApiType?> _extractTypeParameters(
    List<TypeParameterElement> elements,
  ) {
    final result = <String, ApiType?>{};
    for (final e in elements) {
      if (e.name != null) {
        result[e.name!] = e.bound != null ? _describeType(e.bound!) : null;
      }
    }
    return result;
  }

  Map<ClassElement, Set<InterfaceElement>>
  _getOrComputeImmediateSubinterfaceMap(LibraryElement library) {
    if (_immediateSubinterfaceCache[library] case final m?) return m;
    final result = <ClassElement, Set<InterfaceElement>>{};
    for (final interface in [
      ...library.classes,
      ...library.mixins,
      ...library.enums,
      ...library.extensionTypes,
    ]..sortBy((e) => e.name ?? '')) {
      for (final superinterface in [
        interface.supertype,
        ...interface.interfaces,
        ...interface.mixins,
        if (interface is MixinElement) ...interface.superclassConstraints,
      ]) {
        if (superinterface == null) continue;
        final superinterfaceElement = superinterface.element;
        if (superinterfaceElement is ClassElement &&
            superinterfaceElement.isSealed) {
          (result[superinterfaceElement] ??= {}).add(interface);
        }
      }
    }
    _immediateSubinterfaceCache[library] = result;
    return result;
  }

  ApiClass _buildClass(
    InterfaceElement element, {
    required bool includeMembers,
    required ApiDeclarationStatus status,
  }) {
    final constructors = <ApiExecutable>[];
    final methods = <ApiExecutable>[];

    if (includeMembers) {
      for (final member in element.children.sortedBy((m) => m.name ?? '')) {
        if (member.name?.startsWith('_') ?? false) continue;

        switch (member) {
          case ConstructorElement():
            if (element is ClassElement &&
                element.isAbstract &&
                (element.isFinal || element.isInterface || element.isSealed) &&
                !member.isFactory) {
              continue;
            }
            if (element is EnumElement && !member.isFactory) continue;
            constructors.add(_buildExecutable(member, status: status));
          case ExecutableElement():
            methods.add(_buildExecutable(member, status: status));
        }
      }
    }

    final modifiers = <ApiClassModifier>[];
    var immediateSubtypes = <String>[];

    if (element is ClassElement) {
      if (element.isSealed) {
        modifiers.add(ApiClassModifier.isSealed);
        final subinterfaces = _getOrComputeImmediateSubinterfaceMap(
          element.library,
        )[element];
        if (subinterfaces != null) {
          immediateSubtypes = subinterfaces.map((e) => e.name ?? '').toList();
          immediateSubtypes.sort();
        }
      } else {
        if (element.isAbstract) modifiers.add(ApiClassModifier.isAbstract);
        if (element.isBase) modifiers.add(ApiClassModifier.isBase);
        if (element.isMixinClass) modifiers.add(ApiClassModifier.isMixin);
        if (element.isInterface) modifiers.add(ApiClassModifier.isInterface);
        if (element.isFinal) modifiers.add(ApiClassModifier.isFinal);
      }
    } else if (element is MixinElement) {
      if (element.isBase) modifiers.add(ApiClassModifier.isBase);
    }
    return ApiClass(
      name: element.name ?? '',
      locationUri: element.library.uri.toString(),
      status: status,
      typeParameters: _extractTypeParameters(element.typeParameters),
      supertype: element is ClassElement
          ? (element.supertype != null
                ? _describeType(element.supertype!)
                : null)
          : null,
      interfaces: element.interfaces.map(_describeType).toList(),
      mixins: element.mixins.map(_describeType).toList(),
      superclassConstraints: element is MixinElement
          ? element.superclassConstraints.map(_describeType).toList()
          : const [],
      modifiers: modifiers,
      immediateSubtypes: immediateSubtypes,
      constructors: constructors,
      methods: methods,
      isExperimental: element.nonSynthetic.metadata.hasExperimental,
      isDeprecated: element.nonSynthetic.metadata.hasDeprecated,
      isVisibleForTesting: _isVisibleForTesting(element),
    );
  }

  ApiExtension _buildExtension(
    ExtensionElement element, {
    required bool includeMembers,
    required ApiDeclarationStatus status,
  }) {
    final methods = <ApiExecutable>[];
    if (includeMembers) {
      for (final member in element.children.sortedBy((m) => m.name ?? '')) {
        if (member.name?.startsWith('_') ?? false) continue;
        if (member is FieldElement) continue;
        if (member is ExecutableElement) {
          methods.add(_buildExecutable(member, status: status));
        }
      }
    }
    return ApiExtension(
      name: element.name ?? '',
      locationUri: element.library.uri.toString(),
      status: status,
      extendedType: _describeType(element.extendedType),
      typeParameters: _extractTypeParameters(element.typeParameters),
      methods: methods,
      isExperimental: element.nonSynthetic.metadata.hasExperimental,
      isDeprecated: element.nonSynthetic.metadata.hasDeprecated,
      isVisibleForTesting: _isVisibleForTesting(element),
    );
  }

  ApiExtensionType _buildExtensionType(
    ExtensionTypeElement element, {
    required bool includeMembers,
    required ApiDeclarationStatus status,
  }) {
    final constructors = <ApiExecutable>[];
    final methods = <ApiExecutable>[];
    if (includeMembers) {
      for (final member in element.children.sortedBy((m) => m.name ?? '')) {
        if (member.name?.startsWith('_') ?? false) continue;
        if (member is FieldElement) continue;
        if (member is ConstructorElement) {
          constructors.add(_buildExecutable(member, status: status));
        } else if (member is ExecutableElement) {
          methods.add(_buildExecutable(member, status: status));
        }
      }
    }
    return ApiExtensionType(
      name: element.name ?? '',
      locationUri: element.library.uri.toString(),
      status: status,
      representationType: _describeType(element.representation.type),
      typeParameters: _extractTypeParameters(element.typeParameters),
      interfaces: element.interfaces.map(_describeType).toList(),
      constructors: constructors,
      methods: methods,
      isExperimental: element.nonSynthetic.metadata.hasExperimental,
      isDeprecated: element.nonSynthetic.metadata.hasDeprecated,
      isVisibleForTesting: _isVisibleForTesting(element),
    );
  }

  ApiExecutable _buildExecutable(
    ExecutableElement element, {
    required ApiDeclarationStatus status,
  }) {
    final nonSyntheticElement = element.nonSynthetic;
    final formalParameters = element.type.formalParameters;

    final kind = switch (element) {
      GetterElement() => ApiExecutableKind.getter,
      SetterElement() => ApiExecutableKind.setter,
      MethodElement() => ApiExecutableKind.method,
      ConstructorElement() => ApiExecutableKind.constructor,
      _ => ApiExecutableKind.function,
    };

    final isConst = switch (element) {
      ConstructorElement() => element.isConst,
      PropertyAccessorElement() => element.variable.isConst,
      _ => false,
    };

    final isEnumConstant = switch (element) {
      PropertyAccessorElement(:final variable) =>
        variable is FieldElement && variable.isEnumConstant,
      _ => false,
    };
    return ApiExecutable(
      name: element.apiName,
      locationUri: element.library.uri.toString(),
      status: status,
      kind: kind,
      returnType: _describeType(element.returnType),
      typeParameters: _extractTypeParameters(element.typeParameters),
      parameters: formalParameters
          .map(
            (e) => ApiParameter(
              name: e.name ?? '',
              type: _describeType(e.type),
              isRequired: e.isRequired,
              isNamed: e.isNamed,
              isOptionalPositional: e.isOptionalPositional,
              isDeprecated: e.isDeprecated,
            ),
          )
          .toList(),
      isStatic: element.isStatic,
      isConst: isConst,
      isEnumConstant: isEnumConstant,
      isDeprecated: nonSyntheticElement.metadata.hasDeprecated,
      isExperimental: nonSyntheticElement.metadata.hasExperimental,
      isVisibleForTesting: _isVisibleForTesting(element),
    );
  }

  ApiTypeAlias _buildTypeAlias(
    TypeAliasElement element, {
    required ApiDeclarationStatus status,
  }) => ApiTypeAlias(
    name: element.name ?? '',
    locationUri: element.library.uri.toString(),
    status: status,
    typeParameters: _extractTypeParameters(element.typeParameters),
    aliasedType: _describeType(element.aliasedType),
    isDeprecated: element.nonSynthetic.metadata.hasDeprecated,
    isExperimental: element.nonSynthetic.metadata.hasExperimental,
    isVisibleForTesting: _isVisibleForTesting(element),
  );
}

/// Mutable builder accumulating declarations for a single library.
final class _ApiLibraryBuilder {
  final String uri;
  final bool isPublicEntryPoint;
  final classes = <ApiClass>[];
  final enums = <ApiClass>[];
  final mixins = <ApiClass>[];
  final extensions = <ApiExtension>[];
  final extensionTypes = <ApiExtensionType>[];
  final functions = <ApiExecutable>[];
  final typeAliases = <ApiTypeAlias>[];

  _ApiLibraryBuilder(this.uri, {required this.isPublicEntryPoint});

  ApiLibrary build() {
    classes.sortBy((e) => e.name);
    enums.sortBy((e) => e.name);
    mixins.sortBy((e) => e.name);
    extensions.sortBy((e) => e.name);
    extensionTypes.sortBy((e) => e.name);
    functions.sortBy((e) => e.name);
    typeAliases.sortBy((e) => e.name);
    return ApiLibrary(
      uri: uri,
      isPublicEntryPoint: isPublicEntryPoint,
      classes: classes,
      enums: enums,
      mixins: mixins,
      extensions: extensions,
      extensionTypes: extensionTypes,
      functions: functions,
      typeAliases: typeAliases,
    );
  }
}
