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

import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:test/fake.dart';
import 'package:test/test.dart';

import 'package:unified_analytics/src/constants.dart';
import 'package:unified_analytics/src/enums.dart';
import 'package:unified_analytics/src/log_handler.dart';
import 'package:unified_analytics/src/utils.dart';
import 'package:unified_analytics/unified_analytics.dart';

void main() {
  late FakeAnalytics analytics;
  late Directory homeDirectory;
  late MemoryFileSystem fs;
  late File logFile;

  final testEvent = Event.hotReloadTime(timeMs: 10);
  final propertyEditorEvent = Event.devtoolsEvent(
      label: devtoolsEventLabel,
      screen: propertyEditorId,
      eventCategory: 'test',
      value: 1);
  final devToolsEvent = Event.devtoolsEvent(
      label: devtoolsEventLabel,
      screen: 'inspector',
      eventCategory: 'test',
      value: 1);

  setUp(() {
    fs = MemoryFileSystem.test(style: FileSystemStyle.posix);
    homeDirectory = fs.directory('home');
    logFile = homeDirectory
        .childDirectory(kDartToolDirectoryName)
        .childFile(kLogFileName);

    // Create the initialization analytics instance to onboard the tool
    final initializationAnalytics = Analytics.fake(
      tool: DashTool.flutterTool,
      homeDirectory: homeDirectory,
      dartVersion: 'dartVersion',
      fs: fs,
      platform: DevicePlatform.macos,
    );
    initializationAnalytics.clientShowedMessage();

    // This instance is free to send events since the instance above
    // has confirmed that the client has shown the message
    analytics = Analytics.fake(
      tool: DashTool.flutterTool,
      homeDirectory: homeDirectory,
      dartVersion: 'dartVersion',
      fs: fs,
      platform: DevicePlatform.macos,
    );
  });

  test('Ensure that log file is created', () {
    expect(logFile.existsSync(), true);
  });

  test('LogFileStats is null before events are sent', () {
    expect(analytics.logFileStats(), isNull);
  });

  test('LogFileStats returns valid response after sent events', () async {
    final countOfEventsToSend = 10;

    for (var i = 0; i < countOfEventsToSend; i++) {
      analytics.send(testEvent);
    }

    expect(analytics.logFileStats(), isNotNull);
    expect(logFile.readAsLinesSync().length, countOfEventsToSend);
    expect(analytics.logFileStats()!.recordCount, countOfEventsToSend);
  });

  test('LogFileStats handles granular events', () async {
    final countOfPropertyEditorEventsToSend = 5;
    final countOfDevToolsEventsToSend = 10;

    for (var i = 0; i < countOfPropertyEditorEventsToSend; i++) {
      analytics.send(propertyEditorEvent);
    }
    for (var i = 0; i < countOfDevToolsEventsToSend; i++) {
      analytics.send(devToolsEvent);
    }

    expect(analytics.logFileStats(), isNotNull);
    expect(logFile.readAsLinesSync().length,
        countOfPropertyEditorEventsToSend + countOfDevToolsEventsToSend);
    expect(analytics.logFileStats()!.eventCount['property_editor'],
        countOfPropertyEditorEventsToSend);
    expect(analytics.logFileStats()!.eventCount['devtools_event'],
        countOfDevToolsEventsToSend);
  });

  test('The only record in the log file is malformed', () async {
    // Write invalid json for the only log record
    logFile.writeAsStringSync('{{\n');

    expect(logFile.readAsLinesSync().length, 1);
    final logFileStats = analytics.logFileStats();
    expect(logFileStats, isNull,
        reason: 'Null should be returned since only '
            'one record is in there and it is malformed');

    analytics.sendPendingErrorEvents();
    expect(
        analytics.sentEvents,
        contains(
          Event.analyticsException(
            workflow: 'LogFileStats.logFileStats',
            error: 'FormatException',
            description: 'message: Unexpected character\nsource: {{',
          ),
        ));
  });

  test('The first record is malformed, but rest are valid', () async {
    // Write invalid json for the only log record
    logFile.writeAsStringSync('{{\n');

    final countOfEventsToSend = 10;

    for (var i = 0; i < countOfEventsToSend; i++) {
      analytics.send(testEvent);
    }
    expect(logFile.readAsLinesSync().length, countOfEventsToSend + 1);
    final logFileStats = analytics.logFileStats();

    expect(logFileStats, isNotNull);
    expect(logFileStats!.recordCount, countOfEventsToSend);
  });

  test('Several records are malformed', () async {
    final countOfMalformedRecords = 4;
    for (var i = 0; i < countOfMalformedRecords; i++) {
      final currentContents = logFile.readAsStringSync();
      logFile.writeAsStringSync('$currentContents{{\n');
    }

    final countOfEventsToSend = 10;

    for (var i = 0; i < countOfEventsToSend; i++) {
      analytics.send(testEvent);
    }

    expect(logFile.readAsLinesSync().length,
        countOfEventsToSend + countOfMalformedRecords);
    final logFileStats = analytics.logFileStats();

    analytics.sendPendingErrorEvents();
    expect(logFile.readAsLinesSync().length,
        countOfEventsToSend + countOfMalformedRecords + 1,
        reason:
            'There should have been on error event sent when getting stats');

    expect(logFileStats, isNotNull);
    expect(logFileStats!.recordCount, countOfEventsToSend);
  });

  test('Valid json but invalid keys', () {
    // The second line here is missing the "events" top level
    // key which should cause an error for that record only
    //
    // Important to note that this won't actually cause a FormatException
    // like the other malformed records, instead the LogItem.fromRecord
    // constructor will return null if all the keys are not available
    final contents = '''
{"client_id":"ffcea97b-db5e-4c66-98c2-3942de4fac40","events":[{"name":"hot_reload_time","params":{"timeMs":136}}],"user_properties":{"session_id":{"value":1699385899950},"flutter_channel":{"value":"ey-test-channel"},"host":{"value":"macOS"},"flutter_version":{"value":"Flutter 3.6.0-7.0.pre.47"},"dart_version":{"value":"Dart 2.19.0"},"analytics_pkg_version":{"value":"5.2.0"},"tool":{"value":"flutter-tool"},"local_time":{"value":"2023-11-07 15:37:26.685761 -0500"},"host_os_version":{"value":"Version 14.1 (Build 23B74)"},"locale":{"value":"en"},"client_ide":{"value":"VSCode"}}}
{"client_id":"ffcea97b-db5e-4c66-98c2-3942de4fac40","WRONG_EVENT_KEY":[{"name":"hot_reload_time","params":{"timeMs":136}}],"user_properties":{"session_id":{"value":1699385899950},"flutter_channel":{"value":"ey-test-channel"},"host":{"value":"macOS"},"flutter_version":{"value":"Flutter 3.6.0-7.0.pre.47"},"dart_version":{"value":"Dart 2.19.0"},"analytics_pkg_version":{"value":"5.2.0"},"tool":{"value":"flutter-tool"},"local_time":{"value":"2023-11-07 15:37:26.685761 -0500"},"host_os_version":{"value":"Version 14.1 (Build 23B74)"},"locale":{"value":"en"},"client_ide":{"value":"VSCode"}}}
{"client_id":"ffcea97b-db5e-4c66-98c2-3942de4fac40","events":[{"name":"hot_reload_time","params":{"timeMs":136}}],"user_properties":{"session_id":{"value":1699385899950},"flutter_channel":{"value":"ey-test-channel"},"host":{"value":"macOS"},"flutter_version":{"value":"Flutter 3.6.0-7.0.pre.47"},"dart_version":{"value":"Dart 2.19.0"},"analytics_pkg_version":{"value":"5.2.0"},"tool":{"value":"flutter-tool"},"local_time":{"value":"2023-11-07 15:37:26.685761 -0500"},"host_os_version":{"value":"Version 14.1 (Build 23B74)"},"locale":{"value":"en"},"client_ide":{"value":"VSCode"}}}
''';
    logFile.writeAsStringSync(contents);

    final logFileStats = analytics.logFileStats();

    expect(logFile.readAsLinesSync().length, 3);
    expect(logFileStats, isNotNull);
    expect(logFileStats!.recordCount, 2);
  });

  test('Malformed record gets phased out after several events', () async {
    // Write invalid json for the only log record
    logFile.writeAsStringSync('{{\n');

    // Send the max number of events minus two so that we have
    // one malformed record on top of the logs and the rest
    // are valid log records
    //
    // We need to account for the event that is sent when
    // calling [logFileStats()] fails and sends an instance
    // of [Event.analyticsException]
    final recordsToSendInitially = kLogFileLength - 2;
    for (var i = 0; i < recordsToSendInitially; i++) {
      analytics.send(testEvent);
    }
    final logFileStats = analytics.logFileStats();
    analytics.sendPendingErrorEvents();
    expect(analytics.sentEvents.last.eventName, DashEvent.analyticsException,
        reason: 'Calling for the stats should have caused an error');
    expect(logFile.readAsLinesSync().length, kLogFileLength);
    expect(logFileStats, isNotNull);
    expect(logFileStats!.recordCount, recordsToSendInitially,
        reason: 'The first record should be malformed');
    expect(logFile.readAsLinesSync()[0].trim(), '{{');

    // Sending one more event should flush out the malformed record
    analytics.send(testEvent);

    final secondLogFileStats = analytics.logFileStats();
    expect(analytics.sentEvents.last, testEvent);
    expect(secondLogFileStats, isNotNull);
    expect(secondLogFileStats!.recordCount, kLogFileLength);
    expect(logFile.readAsLinesSync()[0].trim(), isNot('{{'));
  });

  test(
      'Catches and discards any FileSystemException raised from attempting '
      'to write to the log file', () async {
    final logFilePath = 'log.txt';
    final fs = MemoryFileSystem.test(opHandle: (context, operation) {
      if (context == logFilePath && operation == FileSystemOp.write) {
        throw FileSystemException(
          'writeFrom failed',
          logFilePath,
          const OSError('No space left on device', 28),
        );
      }
    });
    final logFile = fs.file(logFilePath);
    logFile.createSync();
    final logHandler = LogHandler(logFile: logFile);

    logHandler.save(data: {});
  });

  test('deletes log file larger than kMaxLogFileSize', () async {
    var deletedLargeLogFile = false;
    var wroteDataToLogFile = false;
    const data = <String, Object?>{};
    final logFile = _FakeFile('log.txt')
      .._deleteSyncImpl = (() => deletedLargeLogFile = true)
      .._createSyncImpl = () {}
      .._statSyncImpl = (() => _FakeFileStat(kMaxLogFileSize + 1))
      .._writeAsStringSync = (contents, {mode = FileMode.append}) {
        expect(contents.trim(), data.toString());
        expect(mode, FileMode.writeOnlyAppend);
        wroteDataToLogFile = true;
      };
    final logHandler = LogHandler(logFile: logFile);

    logHandler.save(data: data);
    expect(deletedLargeLogFile, isTrue);
    expect(wroteDataToLogFile, isTrue);
  });

  test('does not delete log file if smaller than kMaxLogFileSize', () async {
    var wroteDataToLogFile = false;
    const data = <String, Object?>{};
    final logFile = _FakeFile('log.txt')
      .._deleteSyncImpl =
          (() => fail('called logFile.deleteSync() when file was less than '
              'kMaxLogFileSize'))
      .._createSyncImpl = () {}
      .._readAsLinesSyncImpl = (() => ['three', 'previous', 'lines'])
      .._statSyncImpl = (() => _FakeFileStat(kMaxLogFileSize - 1))
      .._writeAsStringSync = (contents, {mode = FileMode.append}) {
        expect(contents.trim(), data.toString());
        expect(mode, FileMode.writeOnlyAppend);
        wroteDataToLogFile = true;
      };
    final logHandler = LogHandler(logFile: logFile);

    logHandler.save(data: data);
    expect(wroteDataToLogFile, isTrue);
  });

  test('Catching cast errors for each log record silently', () async {
    // Write a json array to the log file which will cause
    // a cast error when parsing each line
    logFile.writeAsStringSync('[{}, 1, 2, 3]\n');

    final logFileStats = analytics.logFileStats();
    expect(logFileStats, isNull);

    // Ensure it will work as expected after writing correct logs
    final countOfEventsToSend = 10;
    for (var i = 0; i < countOfEventsToSend; i++) {
      analytics.send(testEvent);
    }
    analytics.sendPendingErrorEvents();
    final secondLogFileStats = analytics.logFileStats();

    expect(secondLogFileStats, isNotNull);
    expect(secondLogFileStats!.recordCount, countOfEventsToSend + 1,
        reason: 'Plus one for the error event that is sent '
            'from the first logFileStats call');
  });

  test(
      'truncateStringToLength returns same string when '
      'max length greater than string length', () {
    final testString = 'Version 14.1 (Build 23B74)';
    final maxLength = 100;

    expect(testString.length < maxLength, true);

    String runTruncateString() => truncateStringToLength(testString, maxLength);

    expect(runTruncateString, returnsNormally);

    final newString = runTruncateString();
    expect(newString, testString);
  });

  test(
      'truncateStringToLength returns truncated string when '
      'max length less than string length', () {
    final testString = 'Version 14.1 (Build 23B74)';
    final maxLength = 10;

    expect(testString.length > maxLength, true);

    String runTruncateString() => truncateStringToLength(testString, maxLength);

    expect(runTruncateString, returnsNormally);

    final newString = runTruncateString();
    expect(newString.length, maxLength);
    expect(newString, 'Version 14');
  });

  test('truncateStringToLength handle errors for invalid max length', () {
    final testString = 'Version 14.1 (Build 23B74)';
    var maxLength = 0;
    String runTruncateString() => truncateStringToLength(testString, maxLength);

    expect(runTruncateString, throwsArgumentError);

    maxLength = -1;
    expect(runTruncateString, throwsArgumentError);
  });

  test('truncateStringToLength same string when max length is the same', () {
    final testString = 'Version 14.1 (Build 23B74)';
    final maxLength = testString.length;

    String runTruncateString() => truncateStringToLength(testString, maxLength);
    expect(runTruncateString, returnsNormally);

    final newString = runTruncateString();
    expect(newString.length, maxLength);
    expect(newString, testString);
  });
}

class _FakeFileStat extends Fake implements FileStat {
  _FakeFileStat(this.size);

  @override
  final int size;
}

class _FakeFile extends Fake implements File {
  _FakeFile(this.path);

  List<String> Function()? _readAsLinesSyncImpl;

  @override
  List<String> readAsLinesSync({Encoding encoding = utf8}) =>
      _readAsLinesSyncImpl!();

  @override
  final String path;

  FileStat Function()? _statSyncImpl;

  @override
  FileStat statSync() => _statSyncImpl!();

  void Function()? _deleteSyncImpl;

  @override
  void deleteSync({bool recursive = false}) => _deleteSyncImpl!();

  void Function()? _createSyncImpl;

  @override
  void createSync({bool recursive = false, bool exclusive = false}) {
    return _createSyncImpl!();
  }

  void Function(String contents, {FileMode mode})? _writeAsStringSync;

  @override
  void writeAsStringSync(
    String contents, {
    FileMode mode = FileMode.write,
    Encoding encoding = utf8,
    bool flush = false,
  }) =>
      _writeAsStringSync!(contents, mode: mode);
}
