// Copyright 2014 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 'package:file/memory.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/net.dart';
import 'package:flutter_tools/src/reporting/github_template.dart';

import '../src/common.dart';
import '../src/context.dart';
import '../src/testbed.dart';

const String _kShortURL = 'https://www.example.com/short';

void main() {
  group('GitHub template creator', () {
    testUsingContext('similar issues URL', () async {
      final GitHubTemplateCreator creator = GitHubTemplateCreator();
      expect(
        await creator.toolCrashSimilarIssuesGitHubURL('this is a 100% error'),
        _kShortURL
      );
    }, overrides: <Type, Generator>{
      HttpClientFactory: () => () => SuccessShortenURLFakeHttpClient(),
      FileSystem: () => MemoryFileSystem(),
      ProcessManager: () => FakeProcessManager.any(),
    });

    testUsingContext('similar issues URL with network failure', () async {
      final GitHubTemplateCreator creator = GitHubTemplateCreator();
      expect(
        await creator.toolCrashSimilarIssuesGitHubURL('this is a 100% error'),
        'https://github.com/flutter/flutter/issues?q=is%3Aissue+this+is+a+100%25+error'
      );
    }, overrides: <Type, Generator>{
      HttpClientFactory: () => () => FakeHttpClient(),
      FileSystem: () => MemoryFileSystem(),
      ProcessManager: () => FakeProcessManager.any(),
    });

    group('new issue template URL', () {
      StackTrace stackTrace;
      const String command = 'flutter test';
      const String errorString = 'this is a 100% error';
      const String exception = 'failing to succeed!!!';
      const String doctorText = ' [✓] Flutter (Channel report';
      FileSystem fs;

      setUp(() async {
        stackTrace = StackTrace.fromString('trace');
        fs = MemoryFileSystem();
      });

      testUsingContext('shortened', () async {
        final GitHubTemplateCreator creator = GitHubTemplateCreator();
        expect(
            await creator.toolCrashIssueTemplateGitHubURL(command, errorString, exception, stackTrace, doctorText),
            _kShortURL
        );
      }, overrides: <Type, Generator>{
        HttpClientFactory: () => () => SuccessShortenURLFakeHttpClient(),
        FileSystem: () => MemoryFileSystem(),
        ProcessManager: () => FakeProcessManager.any(),
      });

      testUsingContext('with network failure', () async {
        final GitHubTemplateCreator creator = GitHubTemplateCreator();
        expect(
            await creator.toolCrashIssueTemplateGitHubURL(command, errorString, exception, stackTrace, doctorText),
            'https://github.com/flutter/flutter/issues/new?title=%5Btool_crash%5D+this+is+a+100%25+error&body=%23%'
                '23+Command%0A%60%60%60%0Aflutter+test%0A%60%60%60%0A%0A%23%23+Steps+to+Reproduce%0A1.+...'
                '%0A2.+...%0A3.+...%0A%0A%23%23+Logs%0Afailing+to+succeed%21%21%21%0A%60%60%60%0Atrace%0A'
                '%60%60%60%0A%60%60%60%0A+%5B%E2%9C%93%5D+Flutter+%28Channel+report%0A%60%60%60%0A%0A%23%23'
                '+Flutter+Application+Metadata%0ANo+pubspec+in+working+directory.%0A&labels=tool%2Csevere%3A+crash'
        );
      }, overrides: <Type, Generator>{
        HttpClientFactory: () => () => FakeHttpClient(),
        FileSystem: () => MemoryFileSystem(),
        ProcessManager: () => FakeProcessManager.any(),
      });

      testUsingContext('app metadata', () async {
        final GitHubTemplateCreator creator = GitHubTemplateCreator();
        final Directory projectDirectory = fs.currentDirectory;
        final File pluginsFile = projectDirectory.childFile('.flutter-plugins');

        projectDirectory
            .childFile('pubspec.yaml')
            .writeAsStringSync('''
name: failing_app
version: 2.0.1+100
flutter:
  uses-material-design: true
  module:
    androidX: true
    androidPackage: com.example.failing.android
    iosBundleIdentifier: com.example.failing.ios
''');

        pluginsFile
            .writeAsStringSync('''
camera=/fake/pub.dartlang.org/camera-0.5.7+2/
device_info=/fake/pub.dartlang.org/pub.dartlang.org/device_info-0.4.1+4/
        ''');

        final String actualURL = await creator.toolCrashIssueTemplateGitHubURL(command, errorString, exception, stackTrace, doctorText);
        final String actualBody = Uri.parse(actualURL).queryParameters['body'];
        const String expectedBody = '''
## Command
```
flutter test
```

## Steps to Reproduce
1. ...
2. ...
3. ...

## Logs
failing to succeed!!!
```
trace
```
```
 [✓] Flutter (Channel report
```

## Flutter Application Metadata
**Version**: 2.0.1+100
**Material**: true
**Android X**: true
**Module**: true
**Plugin**: false
**Android package**: com.example.failing.android
**iOS bundle identifier**: com.example.failing.ios
### Plugins
camera-0.5.7+2
device_info-0.4.1+4

''';

        expect(actualBody, expectedBody);
      }, overrides: <Type, Generator>{
        HttpClientFactory: () => () => FakeHttpClient(),
        FileSystem: () => fs,
        ProcessManager: () => FakeProcessManager.any(),
      });
    });
  });
}


class SuccessFakeHttpHeaders extends FakeHttpHeaders {
  @override
  List<String> operator [](String name) => <String>[_kShortURL];
}

class SuccessFakeHttpClientResponse extends FakeHttpClientResponse {
  @override
  int get statusCode => 201;

  @override
  HttpHeaders get headers {
    return SuccessFakeHttpHeaders();
  }
}

class SuccessFakeHttpClientRequest extends FakeHttpClientRequest {
  @override
  Future<HttpClientResponse> close() async {
    return SuccessFakeHttpClientResponse();
  }
}

class SuccessShortenURLFakeHttpClient extends FakeHttpClient {
  @override
  Future<HttpClientRequest> postUrl(Uri url) async {
    return SuccessFakeHttpClientRequest();
  }
}
