// 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.

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
