// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:file/file.dart';

import 'common/core.dart';
import 'common/output_utils.dart';
import 'common/package_looping_command.dart';
import 'common/repository_package.dart';

const int _exitBadTableEntry = 3;
const int _exitUnknownPackageEntry = 4;

/// A command to verify repository-level metadata about packages, such as
/// repo README and CODEOWNERS entries.
class RepoPackageInfoCheckCommand extends PackageLoopingCommand {
  /// Creates Dependabot check command instance.
  RepoPackageInfoCheckCommand(super.packagesDir, {super.gitDir});

  late Directory _repoRoot;

  /// Data from the root README.md table of packages.
  final Map<String, List<String>> _readmeTableEntries =
      <String, List<String>>{};

  /// Packages with entries in CODEOWNERS.
  final List<String> _ownedPackages = <String>[];

  @override
  final String name = 'repo-package-info-check';

  @override
  List<String> get aliases => <String>['check-repo-package-info'];

  @override
  final String description =
      'Checks that all packages are listed correctly in the repo README.';

  @override
  final bool hasLongOutput = false;

  @override
  Future<void> initializeRun() async {
    _repoRoot = packagesDir.fileSystem.directory((await gitDir).path);

    // Extract all of the README.md table entries.
    final RegExp namePattern = RegExp(r'\[(.*?)\]\(');
    for (final String line
        in _repoRoot.childFile('README.md').readAsLinesSync()) {
      // Find all the table entries, skipping the header.
      if (line.startsWith('|') &&
          !line.startsWith('| Package') &&
          !line.startsWith('|-')) {
        final List<String> cells = line
            .split('|')
            .map((String s) => s.trim())
            .where((String s) => s.isNotEmpty)
            .toList();
        // Extract the name, removing any markdown escaping.
        final String? name =
            namePattern.firstMatch(cells[0])?.group(1)?.replaceAll(r'\_', '_');
        if (name == null) {
          printError('Unexpected README table line:\n  $line');
          throw ToolExit(_exitBadTableEntry);
        }
        _readmeTableEntries[name] = cells;

        if (!(packagesDir.childDirectory(name).existsSync() ||
            thirdPartyPackagesDir.childDirectory(name).existsSync())) {
          printError('Unknown package "$name" in root README.md table.');
          throw ToolExit(_exitUnknownPackageEntry);
        }
      }
    }

    // Extract all of the CODEOWNERS package entries.
    final RegExp packageOwnershipPattern =
        RegExp(r'^((?:third_party/)?packages/(?:[^/]*/)?([^/]*))/\*\*');
    for (final String line
        in _repoRoot.childFile('CODEOWNERS').readAsLinesSync()) {
      final RegExpMatch? match = packageOwnershipPattern.firstMatch(line);
      if (match == null) {
        continue;
      }
      final String path = match.group(1)!;
      final String name = match.group(2)!;
      if (!_repoRoot.childDirectory(path).existsSync()) {
        printError('Unknown directory "$path" in CODEOWNERS');
        throw ToolExit(_exitUnknownPackageEntry);
      }
      _ownedPackages.add(name);
    }
  }

  @override
  Future<PackageResult> runForPackage(RepositoryPackage package) async {
    final String packageName = package.directory.basename;
    final List<String> errors = <String>[];

    // All packages should have an owner.
    // Platform interface packages are considered to be owned by the app-facing
    // package owner.
    if (!(_ownedPackages.contains(packageName) ||
        package.isPlatformInterface &&
            _ownedPackages.contains(package.directory.parent.basename))) {
      printError('${indentation}Missing CODEOWNERS entry.');
      errors.add('Missing CODEOWNERS entry');
    }

    // Any published package should be in the README table.
    // For federated plugins, only the app-facing package is listed.
    if (package.isPublishable() &&
        (!package.isFederated || package.isAppFacing)) {
      final List<String>? cells = _readmeTableEntries[packageName];

      if (cells == null) {
        printError('${indentation}Missing repo root README.md table entry');
        errors.add('Missing repo root README.md table entry');
      } else {
        // Extract the two parts of a "[label](link)" .md link.
        final RegExp mdLinkPattern = RegExp(r'^\[(.*)\]\((.*)\)$');
        // Possible link targets.
        for (final String cell in cells) {
          final RegExpMatch? match = mdLinkPattern.firstMatch(cell);
          if (match == null) {
            printError(
                '${indentation}Invalid repo root README.md table entry: "$cell"');
            errors.add('Invalid root README.md table entry');
          } else {
            final String encodedIssueTag =
                Uri.encodeComponent(_issueTagForPackage(packageName));
            final String encodedPRTag =
                Uri.encodeComponent(_prTagForPackage(packageName));
            final String anchor = match.group(1)!;
            final String target = match.group(2)!;

            // The anchor should be one of:
            // - The package name (optionally with any underscores escaped)
            // - An image with a name-based link
            // - An image with a tag-based link
            final RegExp packageLink =
                RegExp(r'^!\[.*\]\(https://img.shields.io/pub/.*/'
                    '$packageName'
                    r'(?:\.svg)?\)$');
            final RegExp issueTagLink = RegExp(
                r'^!\[.*\]\(https://img.shields.io/github/issues/flutter/flutter/'
                '$encodedIssueTag'
                r'\?label=\)$');
            final RegExp prTagLink = RegExp(
                r'^!\[.*\]\(https://img.shields.io/github/issues-pr/flutter/packages/'
                '$encodedPRTag'
                r'\?label=\)$');
            if (!(anchor == packageName ||
                anchor == packageName.replaceAll('_', r'\_') ||
                packageLink.hasMatch(anchor) ||
                issueTagLink.hasMatch(anchor) ||
                prTagLink.hasMatch(anchor))) {
              printError(
                  '${indentation}Incorrect anchor in root README.md table: "$anchor"');
              errors.add('Incorrect anchor in root README.md table');
            }

            // The link should be one of:
            // - a relative link to the in-repo package
            // - a pub.dev link to the package
            // - a github label link to the package's label
            final RegExp pubDevLink =
                RegExp('^https://pub.dev/packages/$packageName(?:/score)?\$');
            final RegExp gitHubIssueLink = RegExp(
                '^https://github.com/flutter/flutter/labels/$encodedIssueTag\$');
            final RegExp gitHubPRLink = RegExp(
                '^https://github.com/flutter/packages/labels/$encodedPRTag\$');
            if (!(target == './packages/$packageName/' ||
                target == './third_party/packages/$packageName/' ||
                pubDevLink.hasMatch(target) ||
                gitHubIssueLink.hasMatch(target) ||
                gitHubPRLink.hasMatch(target))) {
              printError(
                  '${indentation}Incorrect link in root README.md table: "$target"');
              errors.add('Incorrect link in root README.md table');
            }
          }
        }
      }
    }

    return errors.isEmpty
        ? PackageResult.success()
        : PackageResult.fail(errors);
  }

  String _prTagForPackage(String packageName) => 'p: $packageName';

  String _issueTagForPackage(String packageName) {
    switch (packageName) {
      case 'google_maps_flutter':
        return 'p: maps';
      case 'webview_flutter':
        return 'p: webview';
      default:
        return 'p: $packageName';
    }
  }
}
