// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only

/// Tests shared FocusFlow logging behavior.
library;

import 'package:scheduler_core/scheduler_core.dart';
import 'package:test/test.dart';

/// Runs shared logger tests.
void main() {
  tearDown(logger.disable);

  group('FocusFlowLogLevel', () {
    test('parses every supported level and trace alias', () {
      expect(FocusFlowLogLevel.tryParse('finest'), FocusFlowLogLevel.finest);
      expect(FocusFlowLogLevel.tryParse('finer'), FocusFlowLogLevel.finer);
      expect(FocusFlowLogLevel.tryParse('fine'), FocusFlowLogLevel.fine);
      expect(FocusFlowLogLevel.tryParse('debug'), FocusFlowLogLevel.debug);
      expect(FocusFlowLogLevel.tryParse('info'), FocusFlowLogLevel.info);
      expect(FocusFlowLogLevel.tryParse('warn'), FocusFlowLogLevel.warn);
      expect(FocusFlowLogLevel.tryParse('error'), FocusFlowLogLevel.error);
      expect(FocusFlowLogLevel.tryParse('trace'), FocusFlowLogLevel.finest);
      expect(FocusFlowLogLevel.tryParse('verbose'), isNull);
    });
  });

  group('FocusFlowLogger', () {
    test('skips lazy messages below the configured level', () {
      final entries = <FocusFlowLogEntry>[];
      final testLogger = FocusFlowLogger(
        minimumLevel: FocusFlowLogLevel.info,
        sink: entries.add,
        now: () => DateTime.utc(2026, 7, 3, 12),
      );
      var evaluated = false;

      testLogger.debug(() {
        evaluated = true;
        return 'expensive debug state';
      });

      expect(evaluated, isFalse);
      expect(entries, isEmpty);
    });

    test('writes enabled lazy messages with timestamps', () {
      final entries = <FocusFlowLogEntry>[];
      final testLogger = FocusFlowLogger(
        minimumLevel: FocusFlowLogLevel.debug,
        sink: entries.add,
        now: () => DateTime.utc(2026, 7, 3, 12),
      );

      testLogger.debug(() => 'computed debug state');

      expect(entries.single.level, FocusFlowLogLevel.debug);
      expect(entries.single.timestamp, DateTime.utc(2026, 7, 3, 12));
      expect(entries.single.message, 'computed debug state');
    });

    test('finest captures caller information for every written level', () {
      final entries = <FocusFlowLogEntry>[];
      final testLogger = FocusFlowLogger(
        minimumLevel: FocusFlowLogLevel.finest,
        sink: entries.add,
        now: () => DateTime.utc(2026, 7, 3, 12),
      );

      testLogger.info('high level message');

      expect(entries.single.caller, contains('focus_flow_logger_test.dart'));
    });

    test('fine captures caller information for warnings and errors', () {
      final entries = <FocusFlowLogEntry>[];
      final testLogger = FocusFlowLogger(
        minimumLevel: FocusFlowLogLevel.fine,
        sink: entries.add,
        now: () => DateTime.utc(2026, 7, 3, 12),
      );

      testLogger.warn('handled warning');

      expect(entries.single.caller, contains('focus_flow_logger_test.dart'));
    });

    test('info does not capture caller information for warnings', () {
      final entries = <FocusFlowLogEntry>[];
      final testLogger = FocusFlowLogger(
        minimumLevel: FocusFlowLogLevel.info,
        sink: entries.add,
        now: () => DateTime.utc(2026, 7, 3, 12),
      );

      testLogger.warn('minimal warning');

      expect(entries.single.caller, isNull);
    });

    test('formats errors and stack traces on a single line', () {
      final entry = FocusFlowLogEntry(
        timestamp: DateTime.utc(2026, 7, 3, 12),
        level: FocusFlowLogLevel.error,
        message: 'bad state',
        caller: '#1 method (file.dart:10:2)',
        error: 'boom',
        stackTrace: StackTrace.fromString('first\nsecond'),
      );

      expect(
        entry.toSingleLine(),
        '2026-07-03T12:00:00.000Z ERROR caller=#1 method (file.dart:10:2) '
        r'bad state | error=boom | stackTrace=first\nsecond',
      );
    });
  });
}
