// 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:convert';
import 'dart:io';

import 'package:fixnum/fixnum.dart';
import 'package:flutter/foundation.dart' show kIsWeb, visibleForTesting;
import 'package:flutter_dashboard/model/branch.pb.dart';
import 'package:http/http.dart' as http;

import '../logic/qualified_task.dart';
import '../model/build_status_response.pb.dart';
import '../model/commit_firestore.pb.dart';
import '../model/commit.pb.dart';
import '../model/commit_status.pb.dart';
import '../model/commit_tasks_status.pb.dart';
import '../model/key.pb.dart';
import '../model/task.pb.dart';
import '../model/task_firestore.pb.dart';
import 'cocoon.dart';

/// CocoonService for interacting with flutter/flutter production build data.
///
/// This queries API endpoints that are hosted on AppEngine.
class AppEngineCocoonService implements CocoonService {
  /// Creates a new [AppEngineCocoonService].
  ///
  /// If a [client] is not specified, a new [http.Client] instance is created.
  AppEngineCocoonService({http.Client? client}) : _client = client ?? http.Client();

  /// Branch on flutter/flutter to default requests for.
  final String _defaultBranch = 'master';

  /// The Cocoon API endpoint to query
  ///
  /// This is the base for all API requests to cocoon
  static const String _baseApiUrl = 'flutter-dashboard.appspot.com';

  /// Json keys from response data.
  static const String kCommitAvatar = 'Avatar';
  static const String kCommitAuthor = 'Author';
  static const String kCommitBranch = 'Branch';
  static const String kCommitCreateTimestamp = 'CreateTimestamp';
  static const String kCommitDocumentName = 'DocumentName';
  static const String kCommitMessage = 'Message';
  static const String kCommitRepositoryPath = 'RepositoryPath';
  static const String kCommitSha = 'Sha';

  static const String kTaskAttempts = 'Attempts';
  static const String kTaskBringup = 'Bringup';
  static const String kTaskBuildList = 'BuildList';
  static const String kTaskBuildNumber = 'BuildNumber';
  static const String kTaskCommitSha = 'CommitSha';
  static const String kTaskCreateTimestamp = 'CreateTimestamp';
  static const String kTaskDocumentName = 'DocumentName';
  static const String kTaskEndTimestamp = 'EndTimestamp';
  static const String kTaskStartTimestamp = 'StartTimestamp';
  static const String kTaskStatus = 'Status';
  static const String kTaskTaskName = 'TaskName';
  static const String kTaskTestFlaky = 'TestFlaky';

  final http.Client _client;

  @override
  Future<CocoonResponse<List<CommitStatus>>> fetchCommitStatuses({
    CommitStatus? lastCommitStatus,
    String? branch,
    required String repo,
  }) async {
    final Map<String, String?> queryParameters = <String, String?>{
      if (lastCommitStatus != null) 'lastCommitKey': lastCommitStatus.commit.key.child.name,
      'branch': branch ?? _defaultBranch,
      'repo': repo,
    };
    final Uri getStatusUrl = apiEndpoint('/api/public/get-status', queryParameters: queryParameters);

    /// This endpoint returns JSON [List<Agent>, List<CommitStatus>]
    final http.Response response = await _client.get(getStatusUrl);

    if (response.statusCode != HttpStatus.ok) {
      return CocoonResponse<List<CommitStatus>>.error('/api/public/get-status returned ${response.statusCode}');
    }

    try {
      final Map<String, dynamic> jsonResponse = jsonDecode(response.body);
      return CocoonResponse<List<CommitStatus>>.data(
        _commitStatusesFromJson(jsonResponse['Statuses']),
      );
    } catch (error) {
      return CocoonResponse<List<CommitStatus>>.error(error.toString());
    }
  }

  @override
  Future<CocoonResponse<List<CommitTasksStatus>>> fetchCommitStatusesFirestore({
    CommitStatus? lastCommitStatus,
    String? branch,
    required String repo,
  }) async {
    final Map<String, String?> queryParameters = <String, String?>{
      if (lastCommitStatus != null) 'lastCommitKey': lastCommitStatus.commit.key.child.name,
      'branch': branch ?? _defaultBranch,
      'repo': repo,
    };
    final Uri getStatusUrl = apiEndpoint('/api/public/get-status-firestore', queryParameters: queryParameters);

    /// This endpoint returns JSON [List<CommitTasksStatus>]
    final http.Response response = await _client.get(getStatusUrl);

    if (response.statusCode != HttpStatus.ok) {
      return CocoonResponse<List<CommitTasksStatus>>.error(
        '/api/public/get-status-firestore returned ${response.statusCode}',
      );
    }

    try {
      final Map<String, dynamic> jsonResponse = jsonDecode(response.body);
      return CocoonResponse<List<CommitTasksStatus>>.data(
        _commitStatusesFromJsonFirestore(jsonResponse['Statuses']),
      );
    } catch (error) {
      return CocoonResponse<List<CommitTasksStatus>>.error(error.toString());
    }
  }

  @override
  Future<CocoonResponse<List<String>>> fetchRepos() async {
    final Uri getReposUrl = apiEndpoint('/api/public/repos');

    // This endpoint returns a JSON array of strings.1
    final http.Response response = await _client.get(getReposUrl);

    if (response.statusCode != HttpStatus.ok) {
      return CocoonResponse<List<String>>.error('$getReposUrl returned ${response.statusCode}');
    }

    List<String> repos;
    try {
      repos = List<String>.from(jsonDecode(response.body) as List<dynamic>);
    } on FormatException {
      return CocoonResponse<List<String>>.error('$getReposUrl had a malformed response');
    }
    return CocoonResponse<List<String>>.data(repos);
  }

  @override
  Future<CocoonResponse<BuildStatusResponse>> fetchTreeBuildStatus({
    String? branch,
    required String repo,
  }) async {
    final Map<String, String?> queryParameters = <String, String?>{
      'branch': branch ?? _defaultBranch,
      'repo': repo,
    };
    final Uri getBuildStatusUrl = apiEndpoint('/api/public/build-status', queryParameters: queryParameters);

    /// This endpoint returns JSON {AnticipatedBuildStatus: [BuildStatus]}
    final http.Response response = await _client.get(getBuildStatusUrl);

    if (response.statusCode != HttpStatus.ok) {
      return CocoonResponse<BuildStatusResponse>.error('/api/public/build-status returned ${response.statusCode}');
    }

    BuildStatusResponse protoResponse;
    try {
      protoResponse = BuildStatusResponse.fromJson(response.body);
    } on FormatException {
      return const CocoonResponse<BuildStatusResponse>.error('/api/public/build-status had a malformed response');
    }
    return CocoonResponse<BuildStatusResponse>.data(protoResponse);
  }

  @override
  Future<CocoonResponse<List<Branch>>> fetchFlutterBranches() async {
    final Uri getBranchesUrl = apiEndpoint('/api/public/get-release-branches');

    /// This endpoint returns JSON {"Branches": List<String>}
    final http.Response response = await _client.get(getBranchesUrl);

    if (response.statusCode != HttpStatus.ok) {
      return CocoonResponse<List<Branch>>.error('/api/public/get-release-branches returned ${response.statusCode}');
    }

    try {
      final List<dynamic> jsonResponse = jsonDecode(response.body);
      final List<Branch> branches = <Branch>[];
      for (final Map<String, dynamic> jsonBranch in jsonResponse) {
        branches.add(
          Branch()
            ..branch = jsonBranch['branch']!
            ..channel = jsonBranch['name']!,
        );
      }
      return CocoonResponse<List<Branch>>.data(branches);
    } catch (error) {
      return CocoonResponse<List<Branch>>.error(error.toString());
    }
  }

  @override
  Future<bool> vacuumGitHubCommits(String idToken) async {
    final Uri refreshGitHubCommitsUrl = apiEndpoint('/api/vacuum-github-commits');
    final http.Response response = await _client.get(
      refreshGitHubCommitsUrl,
      headers: <String, String>{
        'X-Flutter-IdToken': idToken,
      },
    );
    return response.statusCode == HttpStatus.ok;
  }

  @override
  Future<CocoonResponse<bool>> rerunTask(Task task, String? idToken, String repo) async {
    if (idToken == null || idToken.isEmpty) {
      return const CocoonResponse<bool>.error('Sign in to trigger reruns');
    }

    final QualifiedTask qualifiedTask = QualifiedTask.fromTask(task);
    assert(qualifiedTask.isLuci);

    /// This endpoint only returns a status code.
    final Uri postResetTaskUrl = apiEndpoint('/api/reset-prod-task');
    final http.Response response = await _client.post(
      postResetTaskUrl,
      headers: <String, String>{
        'X-Flutter-IdToken': idToken,
      },
      body: jsonEncode(<String, String>{
        'Key': task.key.child.name,
        'Repo': repo,
      }),
    );

    if (response.statusCode == HttpStatus.ok) {
      return const CocoonResponse<bool>.data(true);
    }

    return CocoonResponse<bool>.error('HTTP Code: ${response.statusCode}, ${response.body}');
  }

  /// Construct the API endpoint based on the priority of using a local endpoint
  /// before falling back to the production endpoint.
  ///
  /// This functions resolves the relative url endpoint to the production endpoint
  /// that can be used on web to the production endpoint if running not on web.
  /// This is because only on web a Cocoon backend can be running from the same
  /// host as this Flutter application, but on mobile we need to ping a separate
  /// production endpoint.
  ///
  /// The urlSuffix begins with a slash, e.g. "/api/public/get-status".
  ///
  /// [queryParameters] are appended to the url and are url encoded.
  @visibleForTesting
  Uri apiEndpoint(
    String urlSuffix, {
    Map<String, String?>? queryParameters,
  }) {
    if (kIsWeb) {
      return Uri.base.replace(path: urlSuffix, queryParameters: queryParameters);
    }
    return Uri.https(_baseApiUrl, urlSuffix, queryParameters);
  }

  List<CommitStatus> _commitStatusesFromJson(List<dynamic>? jsonCommitStatuses) {
    assert(jsonCommitStatuses != null);

    final List<CommitStatus> statuses = <CommitStatus>[];

    for (final Map<String, dynamic> jsonCommitStatus in jsonCommitStatuses!) {
      final Map<String, dynamic> checklist = jsonCommitStatus['Checklist'];
      statuses.add(
        CommitStatus()
          ..commit = _commitFromJson(checklist)
          ..branch = _branchFromJson(checklist)!
          ..tasks.addAll(_tasksFromStagesJson(jsonCommitStatus['Stages'])),
      );
    }

    return statuses;
  }

  List<CommitTasksStatus> _commitStatusesFromJsonFirestore(List<dynamic>? jsonCommitStatuses) {
    assert(jsonCommitStatuses != null);
    // TODO(chillers): Remove adapter code to just use proto fromJson method. https://github.com/flutter/cocoon/issues/441

    final List<CommitTasksStatus> statuses = <CommitTasksStatus>[];
    for (final Map<String, dynamic> jsonCommitStatus in jsonCommitStatuses!) {
      final Map<String, dynamic> jsonCommit = jsonCommitStatus['Commit'];

      statuses.add(
        CommitTasksStatus()
          ..commit = _commitFromJsonFirestore(jsonCommit)
          ..branch = _branchFromJsonFirestore(jsonCommit)!
          ..tasks.addAll(_tasksFromJsonFirestore(jsonCommitStatus['Tasks'])),
      );
    }

    return statuses;
  }

  String? _branchFromJson(Map<String, dynamic> jsonChecklist) {
    final Map<String, dynamic> checklist = jsonChecklist['Checklist'];
    return checklist['Branch'] as String?;
  }

  String? _branchFromJsonFirestore(Map<String, dynamic> jsonCommit) {
    return jsonCommit['Branch'] as String?;
  }

  Commit _commitFromJson(Map<String, dynamic> jsonChecklist) {
    final Map<String, dynamic> checklist = jsonChecklist['Checklist'];

    final Map<String, dynamic> commit = checklist['Commit'];
    final Map<String, dynamic> author = commit['Author'];

    final Commit result = Commit()
      ..key = (RootKey()..child = (Key()..name = jsonChecklist['Key'] as String))
      ..timestamp = Int64() + checklist['CreateTimestamp']!
      ..sha = commit['Sha'] as String
      ..author = author['Login'] as String
      ..authorAvatarUrl = author['avatar_url'] as String
      ..repository = checklist['FlutterRepositoryPath'] as String
      ..branch = checklist['Branch'] as String;
    if (commit['Message'] != null) {
      result.message = commit['Message'] as String;
    }
    return result;
  }

  CommitDocument _commitFromJsonFirestore(Map<String, dynamic> jsonCommit) {
    final CommitDocument result = CommitDocument()
      ..documentName = jsonCommit[kCommitDocumentName]
      ..createTimestamp = Int64(jsonCommit[kCommitCreateTimestamp] as int)
      ..sha = jsonCommit[kCommitSha] as String
      ..author = jsonCommit[kCommitAuthor] as String
      ..avatar = jsonCommit[kCommitAvatar] as String
      ..repositoryPath = jsonCommit[kCommitRepositoryPath] as String
      ..branch = jsonCommit[kCommitBranch] as String;
    if (jsonCommit[kCommitMessage] != null) {
      result.message = jsonCommit[kCommitMessage] as String;
    }
    return result;
  }

  List<Task> _tasksFromStagesJson(List<dynamic> json) {
    final List<Task> tasks = <Task>[];

    for (final Map<String, dynamic> jsonStage in json) {
      tasks.addAll(_tasksFromJson(jsonStage['Tasks']));
    }

    return tasks;
  }

  List<Task> _tasksFromJson(List<dynamic> json) {
    final List<Task> tasks = <Task>[];

    for (final Map<String, dynamic> jsonTask in json) {
      //as Iterable<Map<String, Object>>
      tasks.add(_taskFromJson(jsonTask));
    }

    return tasks;
  }

  List<TaskDocument> _tasksFromJsonFirestore(List<dynamic> json) {
    final List<TaskDocument> tasks = <TaskDocument>[];

    for (final Map<String, dynamic> jsonTask in json) {
      //as Iterable<Map<String, Object>>
      tasks.add(_taskFromJsonFirestore(jsonTask));
    }

    return tasks;
  }

  Task _taskFromJson(Map<String, dynamic> json) {
    final Map<String, dynamic> taskData = json['Task'];
    final List<dynamic>? objectRequiredCapabilities = taskData['RequiredCapabilities'] as List<dynamic>?;

    final Task task = Task()
      ..key = (RootKey()..child = (Key()..name = json['Key'] as String))
      ..createTimestamp = Int64(taskData['CreateTimestamp'] as int)
      ..startTimestamp = Int64(taskData['StartTimestamp'] as int)
      ..endTimestamp = Int64(taskData['EndTimestamp'] as int)
      ..name = taskData['Name'] as String
      ..attempts = taskData['Attempts'] as int
      ..isFlaky = taskData['Flaky'] as bool
      ..timeoutInMinutes = taskData['TimeoutInMinutes'] as int
      ..reason = taskData['Reason'] as String
      ..requiredCapabilities.add(objectRequiredCapabilities.toString())
      ..reservedForAgentId = taskData['ReservedForAgentID'] as String
      ..stageName = taskData['StageName'] as String
      ..status = taskData['Status'] as String
      ..isTestFlaky = taskData['TestFlaky'] as bool? ?? false;

    task
      ..buildNumberList = taskData['BuildNumberList'] as String? ?? ''
      ..builderName = taskData['BuilderName'] as String? ?? ''
      ..luciBucket = taskData['LuciBucket'] as String? ?? '';
    return task;
  }

  TaskDocument _taskFromJsonFirestore(Map<String, dynamic> taskModelData) {
    final Map<String, dynamic> taskData = taskModelData['Task'];
    final TaskDocument task = TaskDocument()
      ..createTimestamp = Int64(taskData[kTaskCreateTimestamp] as int)
      ..startTimestamp = Int64(taskData[kTaskStartTimestamp] as int)
      ..endTimestamp = Int64(taskData[kTaskEndTimestamp] as int)
      ..documentName = taskData[kTaskDocumentName] as String
      ..taskName = taskData[kTaskTaskName] as String
      ..attempts = taskData[kTaskAttempts] as int
      ..bringup = taskData[kTaskBringup] as bool
      ..status = taskData[kTaskStatus] as String
      ..testFlaky = taskData[kTaskTestFlaky] as bool? ?? false
      ..buildList = taskModelData[kTaskBuildList] as String
      ..commitSha = taskData[kTaskCommitSha] as String;
    if (taskData[kTaskBuildNumber] != null) {
      task.buildNumber = taskData[kTaskBuildNumber] as int;
    }
    return task;
  }
}
