// 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:flutter/foundation.dart' show kIsWeb, visibleForTesting;
import 'package:http/http.dart' as http;
import 'package:fixnum/fixnum.dart';

import 'package:cocoon_service/protos.dart';

import '../logic/qualified_task.dart';
import 'cocoon.dart';
import 'downloader.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, Downloader downloader})
      : _client = client ?? http.Client(),
        _downloader = downloader ?? Downloader();

  /// 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';

  final http.Client _client;

  final Downloader _downloader;

  @override
  Future<CocoonResponse<List<CommitStatus>>> fetchCommitStatuses({
    CommitStatus lastCommitStatus,
    String branch,
  }) async {
    final Map<String, String> queryParameters = <String, String>{
      if (lastCommitStatus != null) 'lastCommitKey': lastCommitStatus.commit.key.child.name,
      'branch': branch ?? _defaultBranch,
    };
    final String 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, Object> jsonResponse = jsonDecode(response.body);
      return CocoonResponse<List<CommitStatus>>.data(_commitStatusesFromJson(jsonResponse['Statuses']));
    } catch (error) {
      return CocoonResponse<List<CommitStatus>>.error(error.toString());
    }
  }

  @override
  Future<CocoonResponse<bool>> fetchTreeBuildStatus({
    String branch,
  }) async {
    final Map<String, String> queryParameters = <String, String>{
      'branch': branch ?? _defaultBranch,
    };
    final String 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<bool>.error('/api/public/build-status returned ${response.statusCode}');
    }

    Map<String, Object> jsonResponse;
    try {
      jsonResponse = jsonDecode(response.body);
    } catch (error) {
      return const CocoonResponse<bool>.error('/api/public/build-status had a malformed response');
    }

    if (!_isBuildStatusResponseValid(jsonResponse)) {
      return const CocoonResponse<bool>.error('/api/public/build-status had a malformed response');
    }

    return CocoonResponse<bool>.data(jsonResponse['AnticipatedBuildStatus'] == 'Succeeded');
  }

  @override
  Future<CocoonResponse<List<Agent>>> fetchAgentStatuses() async {
    final String getStatusUrl = apiEndpoint('/api/public/get-status');

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

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

    try {
      final Map<String, Object> jsonResponse = jsonDecode(response.body);
      return CocoonResponse<List<Agent>>.data(_agentStatusesFromJson(jsonResponse['AgentStatuses']));
    } catch (error) {
      return CocoonResponse<List<Agent>>.error(error.toString());
    }
  }

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

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

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

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

  @override
  Future<bool> rerunTask(Task task, String idToken) async {
    assert(idToken != null);
    final String postResetTaskUrl = apiEndpoint('/api/reset-devicelab-task');

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

    return response.statusCode == HttpStatus.ok;
  }

  /// Downloads the log for [task] to the local storage of the current device.
  /// Returns true if write was successful, and false if there was a failure.
  ///
  /// Only works on the web platform.
  @override
  Future<bool> downloadLog(Task task, String idToken, String commitSha) async {
    assert(task != null);
    assert(idToken != null);

    final Map<String, String> queryParameters = <String, String>{'ownerKey': task.key.child.name};
    final String getTaskLogUrl = apiEndpoint('/api/get-log', queryParameters: queryParameters);

    // Only show the first 7 characters of the commit sha. This amount is unique
    // enough to allow lookup of a commit.
    final String shortSha = commitSha.substring(0, 7);

    final String fileName = '${task.name}_${shortSha}_${task.attempts}.log';

    return _downloader.download(getTaskLogUrl, fileName, idToken: idToken);
  }

  @override
  Future<CocoonResponse<String>> createAgent(String agentId, List<String> capabilities, String idToken) async {
    assert(agentId != null);
    assert(capabilities.isNotEmpty);
    assert(idToken != null);

    final String createAgentUrl = apiEndpoint('/api/create-agent');

    /// This endpoint returns JSON {'Token': [Token]}
    final http.Response response = await _client.post(
      createAgentUrl,
      headers: <String, String>{'X-Flutter-IdToken': idToken},
      body: jsonEncode(<String, Object>{
        'AgentID': agentId,
        'Capabilities': capabilities,
      }),
    );

    if (response.statusCode != HttpStatus.ok) {
      return const CocoonResponse<String>.error('/api/create-agent did not respond with 200');
    }

    Map<String, Object> responseBody;
    try {
      responseBody = jsonDecode(response.body);
      if (responseBody['Token'] == null) {
        return const CocoonResponse<String>.error('/api/create-agent returned unexpected response');
      }
    } catch (e) {
      return const CocoonResponse<String>.error('/api/create-agent returned unexpected response');
    }

    return CocoonResponse<String>.data(responseBody['Token']);
  }

  @override
  Future<CocoonResponse<String>> authorizeAgent(Agent agent, String idToken) async {
    assert(agent != null);
    assert(idToken != null);

    final String authorizeAgentUrl = apiEndpoint('/api/authorize-agent');

    /// This endpoint returns JSON {'Token': [Token]}
    final http.Response response = await _client.post(
      authorizeAgentUrl,
      headers: <String, String>{'X-Flutter-IdToken': idToken},
      body: jsonEncode(<String, Object>{
        'AgentID': agent.agentId,
      }),
    );

    if (response.statusCode != HttpStatus.ok) {
      return const CocoonResponse<String>.error('/api/authorize-agent did not respond with 200');
    }

    Map<String, Object> responseBody;
    try {
      responseBody = jsonDecode(response.body);
      if (responseBody['Token'] == null) {
        return const CocoonResponse<String>.error('/api/authorize-agent returned unexpected response');
      }
    } catch (e) {
      return const CocoonResponse<String>.error('/api/authorize-agent returned unexpected response');
    }

    return CocoonResponse<String>.data(responseBody['Token']);
  }

  @override
  Future<void> reserveTask(Agent agent, String idToken) async {
    assert(agent != null);
    assert(idToken != null);

    final String reserveTaskUrl = apiEndpoint('/api/reserve-task');

    final http.Response response = await _client.post(
      reserveTaskUrl,
      headers: <String, String>{'X-Flutter-IdToken': idToken},
      body: jsonEncode(<String, Object>{
        'AgentID': agent.agentId,
      }),
    );

    if (response.statusCode != HttpStatus.ok) {
      throw Exception('/api/reserve-task did not respond with 200');
    }

    Map<String, Object> responseBody;
    try {
      responseBody = jsonDecode(response.body);
      if (responseBody['Task'] == null) {
        throw Exception('/api/reserve-task returned unexpected response');
      }
    } catch (e) {
      throw Exception('/api/reserve-task returned unexpected response');
    }
  }

  /// 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
  String apiEndpoint(
    String urlSuffix, {
    Map<String, String> queryParameters,
  }) {
    final Uri uri = Uri.https(_baseApiUrl, urlSuffix, queryParameters);
    final String url = uri.toString();

    return kIsWeb ? url.replaceAll('https://$_baseApiUrl', '') : url;
  }

  /// Check if [Map<String,Object>] follows the format for build-status.
  ///
  /// Template of the response it should receive:
  /// ```json
  /// {
  ///   "AnticipatedBuildStatus": "Succeeded"|"Failed"
  /// }
  /// ```
  bool _isBuildStatusResponseValid(Map<String, Object> response) {
    if (!response.containsKey('AnticipatedBuildStatus')) {
      return false;
    }

    final String treeBuildStatus = response['AnticipatedBuildStatus'];
    if (treeBuildStatus != 'Failed' && treeBuildStatus != 'Succeeded') {
      return false;
    }

    return true;
  }

  List<Agent> _agentStatusesFromJson(List<Object> jsonAgentStatuses) {
    final List<Agent> agents = <Agent>[];

    for (final Map<String, Object> jsonAgent in jsonAgentStatuses) {
      final List<Object> objectCapabilities = jsonAgent['Capabilities'];
      final List<String> capabilities = objectCapabilities.map((Object value) => value.toString()).toList();
      final Agent agent = Agent()
        ..agentId = jsonAgent['AgentID']
        ..healthCheckTimestamp = Int64.parseInt(jsonAgent['HealthCheckTimestamp'].toString())
        ..isHealthy = jsonAgent['IsHealthy']
        ..capabilities.addAll(capabilities)
        ..healthDetails = jsonAgent['HealthDetails'];
      agents.add(agent);
    }

    return agents;
  }

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

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

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

    return statuses;
  }

  String _branchFromJson(Map<String, Object> jsonChecklist) {
    assert(jsonChecklist != null);

    final Map<String, Object> checklist = jsonChecklist['Checklist'];
    return checklist['Branch'];
  }

  Commit _commitFromJson(Map<String, Object> jsonChecklist) {
    assert(jsonChecklist != null);

    final Map<String, Object> checklist = jsonChecklist['Checklist'];

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

    return Commit()
      ..key = (RootKey()..child = (Key()..name = jsonChecklist['Key']))
      ..timestamp = Int64() + checklist['CreateTimestamp']
      ..sha = commit['Sha']
      ..author = author['Login']
      ..authorAvatarUrl = author['avatar_url']
      ..repository = checklist['FlutterRepositoryPath'];
  }

  List<Stage> _stagesFromJson(List<Object> json) {
    assert(json != null);
    final List<Stage> stages = <Stage>[];

    for (final Object jsonStage in json) {
      stages.add(_stageFromJson(jsonStage));
    }

    return stages;
  }

  Stage _stageFromJson(Map<String, Object> json) {
    assert(json != null);
    return Stage()
      ..name = json['Name']
      ..tasks.addAll(_tasksFromJson(json['Tasks']))
      ..taskStatus = json['Status'];
  }

  List<Task> _tasksFromJson(List<Object> json) {
    assert(json != null);
    final List<Task> tasks = <Task>[];

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

    return tasks;
  }

  Task _taskFromJson(Map<String, Object> json) {
    assert(json != null);

    final Map<String, Object> taskData = json['Task'];
    final List<Object> objectRequiredCapabilities = taskData['RequiredCapabilities'];

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

    if (taskData['StageName'] == StageName.luci) {
      task
        ..buildNumberList = taskData['BuildNumberList'] ?? ''
        ..builderName = taskData['BuilderName'] ?? ''
        ..luciBucket = taskData['LuciBucket'] ?? '';
    }
    return task;
  }
}
