// Copyright 2019 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 'dart:mirrors';

import 'package:cocoon_service/cocoon_service.dart';
import 'package:gcloud/db.dart';
import 'package:test/test.dart';

// Statically reference something from the Cocoon library to keep the analyzer
// happy that we're importing it (which we're doing so the mirrors system sees
// the library).
const Type libraryReference = Config;

bool isKind(InstanceMirror annotation) => annotation.reflectee.runtimeType == Kind;
bool isProperty(InstanceMirror annotation) => SymbolName(annotation.type.simpleName).toString().endsWith('Property');

const Map<Symbol, Symbol> propertyAnnotationsTypeToFieldType = <Symbol, Symbol>{
  #BlobProperty: #List,
  #BoolProperty: #bool,
  #DateTimeProperty: #Date,
  #DoubleProperty: #double,
  #IntProperty: #int,
  #ListProperty: #List,
  #ModelKeyProperty: #Key,
  #StringListProperty: #List,
  #StringProperty: #String,
};

void main() {
  final Iterable<LibraryMirror> libraries = currentMirrorSystem()
      .libraries
      .entries
      .where((MapEntry<Uri, LibraryMirror> entry) => entry.key.path.contains('cocoon_service'))
      .map((MapEntry<Uri, LibraryMirror> entry) => entry.value);
  for (LibraryMirror library in libraries) {
    final Iterable<ClassMirror> classes = library.declarations.values
        .whereType<ClassMirror>()
        .where((ClassMirror declaration) => declaration.hasReflectedType)
        .where((ClassMirror declaration) => declaration.metadata.any(isKind));
    for (ClassMirror modelClass in classes) {
      group('${modelClass.reflectedType}', () {
        test('extends Model', () {
          final bool isStringModel = modelClass.superclass!.reflectedType.toString() == 'Model<String>';
          final bool isIntModel = modelClass.superclass!.reflectedType.toString() == 'Model<int>';
          expect(isStringModel || isIntModel, isTrue);
        });

        final Iterable<VariableMirror> propertyVariables = modelClass.declarations.values
            .whereType<VariableMirror>()
            .where((DeclarationMirror declaration) => declaration.metadata.any(isProperty));

        for (VariableMirror variable in propertyVariables) {
          final Iterable<InstanceMirror> propertyAnnotations = variable.metadata.where(isProperty);

          group(SymbolName(variable.simpleName), () {
            test('contains only one property annotation', () {
              expect(propertyAnnotations, hasLength(1));
            });

            test('type matches property annotation type', () {
              final Symbol propertyType = variable.type.simpleName;
              expect(propertyAnnotationsTypeToFieldType[propertyAnnotations.single.type.simpleName], propertyType);
            });

            test('is not static', () {
              expect(variable.isStatic, isFalse);
            });

            test('is not final', () {
              expect(variable.isFinal, isFalse);
            });
          });
        }

        final Iterable<MethodMirror> propertyGetters = modelClass.declarations.values
            .whereType<MethodMirror>()
            .where((MethodMirror method) => method.isGetter)
            .where((DeclarationMirror declaration) => declaration.metadata.any(isProperty));

        for (MethodMirror getter in propertyGetters) {
          final Iterable<InstanceMirror> propertyAnnotations = getter.metadata.where(isProperty);

          group(SymbolName(getter.simpleName), () {
            test('contains only one property annotation', () {
              expect(propertyAnnotations, hasLength(1));
            });

            test('type matches property annotation type', () {
              final Symbol propertyType = getter.returnType.simpleName;
              expect(propertyAnnotationsTypeToFieldType[propertyAnnotations.single.type.simpleName], propertyType);
            });

            test('is not static', () {
              expect(getter.isStatic, isFalse);
            });

            test('has corresponding setter', () {
              final Iterable<MethodMirror> setter = modelClass.declarations.values
                  .whereType<MethodMirror>()
                  .where((MethodMirror method) => method.isSetter)
                  .where((MethodMirror setter) => setter.simpleName == SymbolName(getter.simpleName).asSetter);
              expect(setter, hasLength(1));
            });
          });
        }
      });
    }
  }

  test('SymbolName toString', () {
    expect(const SymbolName(#Foo).toString(), 'Foo');
  });
}

class SymbolName {
  const SymbolName(this.symbol);

  final Symbol symbol;

  static final RegExp symbolToString = RegExp(r'^Symbol\("(.*)"\)$');

  Symbol get asSetter => Symbol('$this=');

  @override
  String toString() {
    final String raw = symbol.toString();
    final RegExpMatch? match = symbolToString.firstMatch(raw);
    return match == null ? raw : match.group(1)!;
  }
}
