import 'package:flutter_test/flutter_test.dart';
import 'package:marianum_mobile/push/push_status.dart';

const _liveProxy = 'https://connect.marianum-fulda.de/push-proxy/';
const _betaProxy = 'https://connect-beta.marianum-fulda.de/push-proxy/';

PushTypeStatus _typeStatus({
  bool nextcloudRegistered = true,
  String? registeredNcBaseUrl = 'https://cloud.marianum-fulda.de',
  String? registeredProxyServer = _liveProxy,
  DateTime? lastRegistrationAt,
  String? lastRegistrationError,
}) => PushTypeStatus(
  nextcloudRegistered: nextcloudRegistered,
  registeredNcBaseUrl: registeredNcBaseUrl,
  registeredProxyServer: registeredProxyServer,
  lastRegistrationAt: lastRegistrationAt,
  lastRegistrationError: lastRegistrationError,
);

PushStatusReport _report({
  bool settingEnabled = true,
  PushCheck osPermission = PushCheck.ok,
  PushCheck serverCapability = PushCheck.ok,
  bool appPasswordPresent = true,
  bool talkAppPasswordPresent = true,
  bool keypairPresent = true,
  PushTypeStatus? general,
  PushTypeStatus? talk,
  String? currentProxyServer = _liveProxy,
}) => PushStatusReport(
  settingEnabled: settingEnabled,
  osPermission: osPermission,
  serverCapability: serverCapability,
  appPasswordPresent: appPasswordPresent,
  talkAppPasswordPresent: talkAppPasswordPresent,
  keypairPresent: keypairPresent,
  general: general ?? _typeStatus(),
  talk: talk ?? _typeStatus(),
  currentProxyServer: currentProxyServer,
);

PushStatusRow _row(List<PushStatusRow> rows, String label) =>
    rows.singleWhere((r) => r.label == label);

void main() {
  group('buildPushStatusRows', () {
    test('healthy chain shows nine ok rows in chain order', () {
      final rows = buildPushStatusRows(_report());
      expect(rows, hasLength(9));
      expect(rows.map((r) => r.label), [
        'Push-Benachrichtigungen aktiviert',
        'Benachrichtigungsberechtigung',
        'Server-Unterstützung',
        'App-Passwörter',
        'Geräteschlüssel',
        'Nextcloud-Registrierung (Allgemein)',
        'Nextcloud-Registrierung (Talk)',
        'Connect-Registrierung (Allgemein)',
        'Connect-Registrierung (Talk)',
      ]);
      expect(rows.every((r) => r.state == PushCheck.ok), isTrue);
    });

    test('disabled setting fails the first row with a hint', () {
      final rows = buildPushStatusRows(_report(settingEnabled: false));
      final row = _row(rows, 'Push-Benachrichtigungen aktiviert');
      expect(row.state, PushCheck.fail);
      expect(row.detail, contains('deaktiviert'));
    });

    test('unloaded capabilities show as unknown, not as failure', () {
      final rows = buildPushStatusRows(
        _report(serverCapability: PushCheck.unknown),
      );
      final row = _row(rows, 'Server-Unterstützung');
      expect(row.state, PushCheck.unknown);
      expect(row.detail, contains('noch nicht geladen'));
    });

    test('missing talk app password fails the password row and names it', () {
      final rows = buildPushStatusRows(_report(talkAppPasswordPresent: false));
      final row = _row(rows, 'App-Passwörter');
      expect(row.state, PushCheck.fail);
      expect(row.detail, contains('Talk-App-Passwort fehlt'));
    });

    test('registered rows carry their URL as detail', () {
      final rows = buildPushStatusRows(_report());
      expect(
        _row(rows, 'Nextcloud-Registrierung (Allgemein)').detail,
        'https://cloud.marianum-fulda.de',
      );
      expect(_row(rows, 'Connect-Registrierung (Talk)').detail, _liveProxy);
    });

    test('a broken talk registration fails only the talk rows', () {
      final rows = buildPushStatusRows(
        _report(
          talk: _typeStatus(
            nextcloudRegistered: false,
            registeredProxyServer: null,
          ),
        ),
      );
      expect(
        _row(rows, 'Nextcloud-Registrierung (Allgemein)').state,
        PushCheck.ok,
      );
      expect(
        _row(rows, 'Connect-Registrierung (Allgemein)').state,
        PushCheck.ok,
      );
      expect(
        _row(rows, 'Nextcloud-Registrierung (Talk)').state,
        PushCheck.fail,
      );
      final talkConnect = _row(rows, 'Connect-Registrierung (Talk)');
      expect(talkConnect.state, PushCheck.fail);
      expect(talkConnect.detail, contains('ausstehend'));
    });

    test('proxy endpoint mismatch fails the affected row naming both URLs', () {
      final report = _report(
        talk: _typeStatus(registeredProxyServer: _liveProxy),
        currentProxyServer: _betaProxy,
        general: _typeStatus(registeredProxyServer: _betaProxy),
      );
      expect(report.proxyEndpointMismatch(report.talk), isTrue);
      expect(report.proxyEndpointMismatch(report.general), isFalse);
      final row = _row(
        buildPushStatusRows(report),
        'Connect-Registrierung (Talk)',
      );
      expect(row.state, PushCheck.fail);
      expect(row.detail, contains('connect.marianum-fulda.de'));
      expect(row.detail, contains('connect-beta.marianum-fulda.de'));
    });

    test('per-type registration errors fail only their own connect row', () {
      final rows = buildPushStatusRows(
        _report(talk: _typeStatus(lastRegistrationError: 'HTTP 404')),
      );
      expect(
        _row(rows, 'Connect-Registrierung (Allgemein)').state,
        PushCheck.ok,
      );
      final talkRow = _row(rows, 'Connect-Registrierung (Talk)');
      expect(talkRow.state, PushCheck.fail);
      expect(talkRow.detail, contains('fehlgeschlagen'));
    });
  });

  group('PushStatusReport.readyForTestNotification', () {
    test('test push only depends on the general chain', () {
      // Test pushes are Connect direct pushes via the general registration —
      // a broken talk registration must not disable the test action.
      final report = _report(
        talk: _typeStatus(
          nextcloudRegistered: false,
          registeredProxyServer: null,
          lastRegistrationError: 'HTTP 404',
        ),
      );
      expect(report.readyForTestNotification, isTrue);
    });

    test('denied OS permission wins over a complete registration', () {
      expect(
        _report(osPermission: PushCheck.fail).readyForTestNotification,
        isFalse,
      );
    });

    test('undetermined OS permission stays permissive', () {
      expect(
        _report(osPermission: PushCheck.unknown).readyForTestNotification,
        isTrue,
      );
    });

    test('missing general registration is not ready', () {
      expect(
        _report(
          general: _typeStatus(nextcloudRegistered: false),
        ).readyForTestNotification,
        isFalse,
      );
      expect(
        _report(
          general: _typeStatus(registeredProxyServer: null),
        ).readyForTestNotification,
        isFalse,
      );
    });

    test('general endpoint mismatch or failed attempt is not ready', () {
      expect(
        _report(
          general: _typeStatus(registeredProxyServer: _liveProxy),
          talk: _typeStatus(registeredProxyServer: _betaProxy),
          currentProxyServer: _betaProxy,
        ).readyForTestNotification,
        isFalse,
      );
      expect(
        _report(
          general: _typeStatus(lastRegistrationError: 'HTTP 404'),
        ).readyForTestNotification,
        isFalse,
      );
    });
  });
}
