// Copyright (c) 2015, 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:io';

import 'package:dart_services/src/analysis_server.dart';
import 'package:dart_services/src/analysis_servers.dart';
import 'package:dart_services/src/common.dart';
import 'package:dart_services/src/common_server_impl.dart';
import 'package:dart_services/src/protos/dart_services.pbserver.dart';
import 'package:dart_services/src/sdk.dart';
import 'package:dart_services/src/server_cache.dart';
import 'package:test/test.dart';

final channel = Platform.environment['FLUTTER_CHANNEL'] ?? stableChannel;
void main() => defineTests();

void defineTests() {
  group('Flutter SDK analysis_server', () {
    late AnalysisServerWrapper analysisServer;

    setUp(() async {
      final sdk = Sdk.create(channel);
      analysisServer =
          FlutterAnalysisServerWrapper(dartSdkPath: sdk.dartSdkPath);
      await analysisServer.init();
    });

    tearDown(() async {
      await analysisServer.shutdown();
    });

    test('analyze counter app', () async {
      final results = await analysisServer.analyze(sampleCodeFlutterCounter);
      expect(results.issues, isEmpty);
    });

    test('analyze Draggable Physics sample', () async {
      final results =
          await analysisServer.analyze(sampleCodeFlutterDraggableCard);
      expect(results.issues, isEmpty);
    });
  });

  group(
      'Flutter SDK analysis_server with analysis '
      'servers', () {
    late AnalysisServersWrapper analysisServersWrapper;
    late Sdk sdk;
    setUp(() async {
      sdk = Sdk.create(channel);
      analysisServersWrapper = AnalysisServersWrapper(sdk.dartSdkPath);
      await analysisServersWrapper.warmup();
    });

    tearDown(() async {
      await analysisServersWrapper.shutdown();
    });

    test('reports errors with Flutter code', () async {
      late AnalysisResults results;
      results = await analysisServersWrapper.analyze('''
import 'package:flutter/material.dart';

String x = 7;

void main() async {
  runApp(MaterialApp(
      debugShowCheckedModeBanner: false, home: Scaffold(body: HelloWorld())));
}

class HelloWorld extends StatelessWidget {
  @override
  Widget build(context) => const Center(child: Text('Hello world'));
}
''', devMode: false);
      expect(results.issues, hasLength(1));
      final issue = results.issues[0];
      expect(issue.line, 3);
      expect(issue.kind, 'error');
      expect(
          issue.message,
          "A value of type 'int' can't be assigned to a variable of type "
          "'String'.");
    });

    // https://github.com/dart-lang/dart-pad/issues/2005
    test('reports lint with Flutter code', () async {
      late AnalysisResults results;
      results = await analysisServersWrapper.analyze('''
import 'package:flutter/material.dart';

void main() async {
  var unknown;
  print(unknown);

  runApp(MaterialApp(
      debugShowCheckedModeBanner: false, home: Scaffold(body: HelloWorld())));
}

class HelloWorld extends StatelessWidget {
  @override
  Widget build(context) => const Center(child: Text('Hello world'));
}
''', devMode: false);
      expect(results.issues, hasLength(1));
      final issue = results.issues[0];
      expect(issue.line, 4);
      expect(issue.kind, 'info');
      expect(issue.message,
          'An uninitialized variable should have an explicit type annotation.');
    });

    test('analyze counter app', () async {
      final results = await analysisServersWrapper
          .analyze(sampleCodeFlutterCounter, devMode: false);
      expect(results.issues, isEmpty);
    });

    test('analyze Draggable Physics sample', () async {
      final results = await analysisServersWrapper
          .analyze(sampleCodeFlutterDraggableCard, devMode: false);
      expect(results.issues, isEmpty);
    });

    test('analyze counter app', () async {
      final results = await analysisServersWrapper
          .analyze(sampleCodeFlutterCounter, devMode: false);
      expect(results.issues, isEmpty);
    });

    test('analyze Draggable Physics sample', () async {
      final results = await analysisServersWrapper
          .analyze(sampleCodeFlutterDraggableCard, devMode: false);
      expect(results.issues, isEmpty);
    });
  });

  group('CommonServerImpl flutter analyze', () {
    late CommonServerImpl commonServerImpl;

    _MockCache cache;

    setUp(() async {
      cache = _MockCache();
      final sdk = Sdk.create(channel);
      commonServerImpl = CommonServerImpl(cache, sdk);
      await commonServerImpl.init();
    });

    tearDown(() async {
      await commonServerImpl.shutdown();
    });

    test('counter app', () async {
      final results = await commonServerImpl
          .analyze(SourceRequest()..source = sampleCodeFlutterCounter);
      expect(results.issues, isEmpty);
    });

    test('Draggable Physics sample', () async {
      final results = await commonServerImpl
          .analyze(SourceRequest()..source = sampleCodeFlutterDraggableCard);
      expect(results.issues, isEmpty);
    });
  });

  ///----------------------------------------------------------------
  /// Beginning of multi file files={} tests group:
  group('MULTI FILE files={} Tests', () {
    group('Flutter SDK analysis_server files={} variation', () {
      late AnalysisServerWrapper analysisServer;

      setUp(() async {
        final sdk = Sdk.create(channel);
        analysisServer =
            FlutterAnalysisServerWrapper(dartSdkPath: sdk.dartSdkPath);
        await analysisServer.init();
      });

      tearDown(() async {
        await analysisServer.shutdown();
      });

      test('analyzeFiles counter app files={}', () async {
        final results = await analysisServer
            .analyzeFiles({kMainDart: sampleCodeFlutterCounter});
        expect(results.issues, isEmpty);
      });

      test('analyzeFiles Draggable Physics sample files={}', () async {
        final results = await analysisServer
            .analyzeFiles({kMainDart: sampleCodeFlutterDraggableCard});
        expect(results.issues, isEmpty);
      });
    });

    group(
        'Flutter SDK analysis_server with analysis files={}'
        'servers', () {
      late AnalysisServersWrapper analysisServersWrapper;
      late Sdk sdk;
      setUp(() async {
        sdk = Sdk.create(channel);
        analysisServersWrapper = AnalysisServersWrapper(sdk.dartSdkPath);
        await analysisServersWrapper.warmup();
      });

      tearDown(() async {
        await analysisServersWrapper.shutdown();
      });

      test('reports errors with Flutter code files={}', () async {
        late AnalysisResults results;
        results = await analysisServersWrapper.analyzeFiles({
          kMainDart: '''
import 'package:flutter/material.dart';

String x = 7;

void main() async {
  runApp(MaterialApp(
      debugShowCheckedModeBanner: false, home: Scaffold(body: HelloWorld())));
}

class HelloWorld extends StatelessWidget {
  @override
  Widget build(context) => const Center(child: Text('Hello world'));
}
'''
        }, kMainDart, devMode: false);
        expect(results.issues, hasLength(1));
        final issue = results.issues[0];
        expect(issue.line, 3);
        expect(issue.kind, 'error');
        expect(
            issue.message,
            "A value of type 'int' can't be assigned to a variable of type "
            "'String'.");
      });

      // https://github.com/dart-lang/dart-pad/issues/2005
      test('reports lint with Flutter code files={}', () async {
        late AnalysisResults results;
        results = await analysisServersWrapper.analyzeFiles({
          kMainDart: '''
import 'package:flutter/material.dart';

void main() async {
  var unknown;
  print(unknown);

  runApp(MaterialApp(
      debugShowCheckedModeBanner: false, home: Scaffold(body: HelloWorld())));
}

class HelloWorld extends StatelessWidget {
  @override
  Widget build(context) => const Center(child: Text('Hello world'));
}
'''
        }, kMainDart, devMode: false);
        expect(results.issues, hasLength(1));
        final issue = results.issues[0];
        expect(issue.line, 4);
        expect(issue.kind, 'info');
        expect(issue.message,
            'An uninitialized variable should have an explicit type annotation.');
      });

      test('analyzeFiles counter app files={}', () async {
        final results = await analysisServersWrapper.analyzeFiles(
            {kMainDart: sampleCodeFlutterCounter}, kMainDart,
            devMode: false);
        expect(results.issues, isEmpty);
      });

      test('analyzeFiles Draggable Physics sample files={}', () async {
        final results = await analysisServersWrapper.analyzeFiles(
            {kMainDart: sampleCodeFlutterDraggableCard}, kMainDart,
            devMode: false);
        expect(results.issues, isEmpty);
      });

      test('analyzeFiles counter app files={}', () async {
        final results = await analysisServersWrapper.analyzeFiles(
            {kMainDart: sampleCodeFlutterCounter}, kMainDart,
            devMode: false);
        expect(results.issues, isEmpty);
      });

      test('analyzeFiles Draggable Physics sample files={}', () async {
        final results = await analysisServersWrapper.analyzeFiles(
            {kMainDart: sampleCodeFlutterDraggableCard}, kMainDart,
            devMode: false);
        expect(results.issues, isEmpty);
      });
    });

    group('CommonServerImpl flutter analyzeFiles files={}', () {
      late CommonServerImpl commonServerImpl;

      _MockCache cache;

      setUp(() async {
        cache = _MockCache();
        final sdk = Sdk.create(channel);
        commonServerImpl = CommonServerImpl(cache, sdk);
        await commonServerImpl.init();
      });

      tearDown(() async {
        await commonServerImpl.shutdown();
      });

      test('counter app files={}', () async {
        final results = await commonServerImpl.analyzeFiles(SourceFilesRequest()
          ..files.addAll({kMainDart: sampleCodeFlutterCounter})
          ..activeSourceName = kMainDart
          ..offset = 0);
        expect(results.issues, isEmpty);
      });

      test('Draggable Physics sample files={}', () async {
        final results = await commonServerImpl.analyzeFiles(SourceFilesRequest()
          ..files.addAll({kMainDart: sampleCodeFlutterDraggableCard})
          ..activeSourceName = kMainDart);
        expect(results.issues, isEmpty);
      });
    });
  });
}

class _MockCache implements ServerCache {
  @override
  Future<String?> get(String key) => Future<String?>.value(null);

  @override
  Future<void> set(String key, String value, {Duration? expiration}) =>
      Future.value();

  @override
  Future<void> remove(String key) => Future.value();

  @override
  Future<void> shutdown() => Future.value();
}
