import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:chanora_flutter/l10n/generated/app_localizations_en.dart';
import 'package:chanora_flutter/services/connection_phase_state.dart';

void main() {
  final l10n = AppL10nEn();

  test('connection phases expose shared predicates', () {
    expect(ConnectionPhase.idle.isServerReachable, isFalse);
    expect(ConnectionPhase.connecting.isServerReachable, isFalse);
    expect(ConnectionPhase.synchronizing.isServerReachable, isTrue);
    expect(ConnectionPhase.connected.isServerReachable, isTrue);
    expect(ConnectionPhase.reconnecting.isServerReachable, isTrue);
    expect(ConnectionPhase.disconnected.isServerReachable, isFalse);

    expect(ConnectionPhase.synchronizing.canOpenChat, isTrue);
    expect(ConnectionPhase.connected.canOpenChat, isTrue);
    expect(ConnectionPhase.reconnecting.canOpenChat, isFalse);
    expect(ConnectionPhase.connected.canDisconnect, isTrue);
  });

  test('server-reachable phases show loading until snapshot is available', () {
    expect(
      ConnectionPhase.connecting.shouldShowSnapshotLoading(hasSnapshot: false),
      isFalse,
    );
    expect(
      ConnectionPhase.synchronizing.shouldShowSnapshotLoading(
        hasSnapshot: false,
      ),
      isTrue,
    );
    expect(
      ConnectionPhase.connected.shouldShowSnapshotLoading(hasSnapshot: false),
      isTrue,
    );
    expect(
      ConnectionPhase.reconnecting.shouldShowSnapshotLoading(
        hasSnapshot: false,
      ),
      isTrue,
    );
    expect(
      ConnectionPhase.synchronizing.shouldShowSnapshotLoading(
        hasSnapshot: true,
      ),
      isFalse,
    );
  });

  test('chat only opens after a snapshot is available', () {
    expect(
      ConnectionPhase.synchronizing.canOpenChatWithSnapshot(hasSnapshot: false),
      isFalse,
    );
    expect(
      ConnectionPhase.synchronizing.canOpenChatWithSnapshot(hasSnapshot: true),
      isTrue,
    );
    expect(
      ConnectionPhase.connected.canOpenChatWithSnapshot(hasSnapshot: true),
      isTrue,
    );
    expect(
      ConnectionPhase.reconnecting.canOpenChatWithSnapshot(hasSnapshot: true),
      isFalse,
    );
  });

  test('snapshot application completes synchronizing phase', () {
    expect(
      phaseAfterSnapshotApplied(ConnectionPhase.synchronizing),
      ConnectionPhase.connected,
    );
    expect(
      phaseAfterSnapshotApplied(ConnectionPhase.connected),
      ConnectionPhase.connected,
    );
    expect(
      phaseAfterSnapshotApplied(ConnectionPhase.reconnecting),
      ConnectionPhase.reconnecting,
    );
  });

  test('connection status text maps all phases', () {
    expect(
      connectionStatusText(phase: ConnectionPhase.idle, l10n: l10n),
      l10n.statusIdle,
    );
    expect(
      connectionStatusText(phase: ConnectionPhase.connecting, l10n: l10n),
      l10n.statusConnecting,
    );
    expect(
      connectionStatusText(phase: ConnectionPhase.synchronizing, l10n: l10n),
      'Synchronizing...',
    );
    expect(
      connectionStatusText(
        phase: ConnectionPhase.connected,
        l10n: l10n,
        serverName: 'Server',
      ),
      'Connected to Server',
    );
    expect(
      connectionStatusText(
        phase: ConnectionPhase.reconnecting,
        l10n: l10n,
        reconnectAttempt: 2,
        reconnectDelay: 5,
      ),
      l10n.statusReconnecting(2, 5),
    );
    expect(
      connectionStatusText(
        phase: ConnectionPhase.reconnecting,
        l10n: l10n,
        lostReason: 'network',
      ),
      'Connection lost: network',
    );
    expect(
      connectionStatusText(phase: ConnectionPhase.disconnected, l10n: l10n),
      l10n.statusIdle,
    );
  });

  test('connection phases map to token icons', () {
    final scheme = ColorScheme.fromSeed(seedColor: Colors.indigo);

    expect(ConnectionPhase.idle.tokens(scheme).icon, Icons.cloud_off);
    expect(ConnectionPhase.connecting.tokens(scheme).icon, Icons.sync);
    expect(
      ConnectionPhase.synchronizing.tokens(scheme).icon,
      Icons.hourglass_top,
    );
    expect(ConnectionPhase.connected.tokens(scheme).icon, Icons.cloud_done);
    expect(ConnectionPhase.reconnecting.tokens(scheme).icon, Icons.restart_alt);
    expect(ConnectionPhase.disconnected.tokens(scheme).icon, Icons.cloud_off);
  });

  test('connected event preserves connected phase when snapshot exists', () {
    expect(
      phaseAfterConnectedEvent(ConnectionPhase.connected, hasSnapshot: true),
      ConnectionPhase.connected,
    );
  });

  test('connected event synchronizes when snapshot is missing', () {
    expect(
      phaseAfterConnectedEvent(ConnectionPhase.connected, hasSnapshot: false),
      ConnectionPhase.synchronizing,
    );
    expect(
      phaseAfterConnectedEvent(ConnectionPhase.reconnecting, hasSnapshot: true),
      ConnectionPhase.synchronizing,
    );
  });
}
