// 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:async';
import 'dart:typed_data';

import 'package:appengine/appengine.dart';
import 'package:gcloud/db.dart';
import 'package:meta/meta.dart';

import '../datastore/cocoon_config.dart';
import '../model/appengine/key_helper.dart';
import '../model/appengine/log_chunk.dart';
import '../model/appengine/task.dart';
import '../request_handling/api_request_handler.dart';
import '../request_handling/authentication.dart';
import '../request_handling/body.dart';
import '../request_handling/exceptions.dart';
import '../service/datastore.dart';
import '../service/stackdriver_logger.dart';

@immutable
class AppendLog extends ApiRequestHandler<Body> {
  AppendLog(
    Config config,
    AuthenticationProvider authenticationProvider, {
    @visibleForTesting
        this.datastoreProvider = DatastoreService.defaultProvider,
    StackdriverLoggerService stackdriverLogger,
    @visibleForTesting Uint8List requestBodyValue,
  })  : stackdriverLogger =
            stackdriverLogger ?? StackdriverLoggerService(config: config),
        super(
            config: config,
            authenticationProvider: authenticationProvider,
            requestBodyValue: requestBodyValue);

  final StackdriverLoggerService stackdriverLogger;
  final DatastoreServiceProvider datastoreProvider;

  static const String ownerKeyParam = 'ownerKey';

  @override
  Future<Body> post() async {
    final DatastoreService datastore = datastoreProvider(config.db);
    final String encodedOwnerKey = request.uri.queryParameters[ownerKeyParam];
    if (encodedOwnerKey == null) {
      throw const BadRequestException(
          'Missing required query parameter: $ownerKeyParam');
    }

    final ClientContext clientContext = authContext.clientContext;
    final KeyHelper keyHelper =
        KeyHelper(applicationContext: clientContext.applicationContext);
    final Key ownerKey = keyHelper.decode(encodedOwnerKey);

    final Task task =
        await datastore.lookupByValue<Model>(ownerKey, orElse: () {
      throw const InternalServerError(
          'Invalid owner key. Owner entity does not exist');
    }) as Task;

    final LogChunk logChunk = LogChunk(
      ownerKey: ownerKey,
      createTimestamp: DateTime.now().millisecondsSinceEpoch,
      data: requestBody,
    );

    await datastore.insert(<LogChunk>[logChunk]);
    await writeToStackdriver('${encodedOwnerKey}_${task.attempts}');

    return Body.empty;
  }

  /// Write the log data from this request to Stackdriver under [logName].
  ///
  /// [logName] must follow the format `[encodedOwnerKey]_[task.attempt]` so each
  /// attempt for a task can be located.
  ///
  /// This will write the log to the global path `projects/flutter-dashboard/logs/[logName]` on Google Cloud.
  Future<void> writeToStackdriver(String logName) async {
    final List<String> lines = String.fromCharCodes(requestBody).split('\n');
    await stackdriverLogger.writeLines(logName, lines);
  }
}
