// Copyright (c) 2021, 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.

// @dart = 2.9

import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analysis_server/src/services/linter/lint_names.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'fix_processor.dart';

void main() {
  defineReflectiveSuite(() {
    // defineReflectiveTests(MultiFixInFileTest);
    defineReflectiveTests(SingleFixInFileTest);
  });

  VerificationTests.defineTests();
}

//// todo (pq): update w/ a FixKind that we're sure we want to support as a file fix
// @reflectiveTest
// class MultiFixInFileTest extends FixInFileProcessorTest
//     with WithNullSafetyMixin {
//   Future<void> test_nullable() async {
//     await resolveTestCode('''
// class C {
//   String? s;
//   String? s2;
//   C({String this.s, String this.s2});
// }
// ''');
//
//     var fixes = await getFixes();
//     expect(fixes, hasLength(2));
//
//     var addRequired =
//         fixes.where((f) => f.kind == DartFixKind.ADD_REQUIRED).first;
//     assertProduces(addRequired, '''
// class C {
//   String? s;
//   String? s2;
//   C({required String this.s, required String this.s2});
// }
// ''');
//
//     var makeNullable =
//         fixes.where((f) => f.kind == DartFixKind.MAKE_VARIABLE_NULLABLE).first;
//     assertProduces(makeNullable, '''
// class C {
//   String? s;
//   String? s2;
//   C({String? this.s, String? this.s2});
// }
// ''');
//   }
// }

@reflectiveTest
class SingleFixInFileTest extends FixInFileProcessorTest {
  Future<void> test_fix_lint_annotate_overrides() async {
    createAnalysisOptionsFile(lints: [LintNames.annotate_overrides]);
    await resolveTestCode('''
class A {
  void a() {}
  void aa() {}
}

class B extends A {
  void a() {}
  void aa() {}
}
''');
    var fixes = await getFixesForFirstError();
    expect(fixes, hasLength(1));
    assertProduces(fixes.first, '''
class A {
  void a() {}
  void aa() {}
}

class B extends A {
  @override
  void a() {}
  @override
  void aa() {}
}
''');
  }

  Future<void> test_fix_nonLint_isNull() async {
    await resolveTestCode('''
bool f(p, q) {
  return p is Null && q is Null;
}
''');

    var fixes = await getFixesForFirstError();
    expect(fixes, hasLength(1));
    assertProduces(fixes.first, '''
bool f(p, q) {
  return p == null && q == null;
}
''');
  }

  Future<void> test_noFixes() async {
    await resolveTestCode('''
bool f(p, q) {
  return p is Null;
}
''');

    var fixes = await getFixesForFirstError();
    expect(fixes, isEmpty);
  }
}

class VerificationTests {
  static void defineTests() {
    verify_fixInFileFixesHaveBulkFixTests();
    verify_fixInFileFixKindsHaveMultiFixes();
    verify_fixInFileFixesHaveUniqueBulkFixes();
  }

  static void verify_fixInFileFixesHaveBulkFixTests() {
    group('VerificationTests | fixInFileFixesHaveBulkFixTests |', () {
      for (var fixEntry in FixProcessor.lintProducerMap.entries) {
        var errorCode = fixEntry.key;
        for (var fixInfo in fixEntry.value) {
          if (fixInfo.canBeAppliedToFile) {
            test('$errorCode |', () {
              expect(fixInfo.canBeBulkApplied, isTrue);
            });
          }
        }
      }
    });
  }

  static void verify_fixInFileFixesHaveUniqueBulkFixes() {
    group('VerificationTests | fixInFileFixesHaveUniqueBulkFixes | lint |', () {
      for (var fixEntry in FixProcessor.lintProducerMap.entries) {
        var errorCode = fixEntry.key;
        for (var fixInfo in fixEntry.value) {
          if (fixInfo.canBeAppliedToFile) {
            test('$errorCode |', () {
              for (var generator in fixInfo.generators) {
                var g = generator();
                var multiFixKind = g.multiFixKind;
                var fixKind = g.fixKind;
                if (multiFixKind != null) {
                  expect(multiFixKind, isNot(equals(fixKind)));
                }
              }
              expect(fixInfo.canBeBulkApplied, isTrue);
            });
          }
        }
      }
    });
  }

  static void verify_fixInFileFixKindsHaveMultiFixes() {
    // todo (pq): find a better way to verify dynamic producers.
    var dynamicProducerTypes = ['ReplaceWithIsEmpty'];

    group('VerificationTests | fixInFileFixKindsHaveMultiFixes | lint |', () {
      for (var fixEntry in FixProcessor.lintProducerMap.entries) {
        var errorCode = fixEntry.key;
        for (var fixInfo in fixEntry.value) {
          // At least one generator should have a multiFix.
          if (fixInfo.canBeAppliedToFile) {
            test('$errorCode |', () {
              var generators = fixInfo.generators;
              var foundMultiFix = false;
              for (var i = 0; i < generators.length && !foundMultiFix; ++i) {
                var generator = generators[i]();
                foundMultiFix = generator.multiFixKind != null ||
                    dynamicProducerTypes
                        .contains(generator.runtimeType.toString());
              }
              expect(foundMultiFix, isTrue);
            });
          }
        }
      }
    });
  }
}

/// todo (pq): add negative tests
