import 'package:flutter_test/flutter_test.dart';
import 'package:smplayer/shared/widgets/version_grouping.dart';
import 'package:smplayer/shared/widgets/version_source_card.dart';

void main() {
  VersionSourceCardData createEntry({
    required String serverName,
    required String sourceKey,
    String? serverKey,
    int? sizeBytes = 1000,
    String resolutionLabel = '4K',
    bool isCurrent = false,
    bool selected = false,
  }) {
    return VersionSourceCardData(
      topLabel: '$resolutionLabel SDR',
      serverName: serverName,
      serverKey: serverKey ?? sourceKey.split('|').first,
      sourceKey: sourceKey,
      sizeBytes: sizeBytes,
      resolutionLabel: resolutionLabel,
      isCurrent: isCurrent,
      selected: selected,
    );
  }

  group('groupVersionEntries', () {
    test('merges equal size and resolution in source order', () {
      final firstEntry = createEntry(
        serverName: 'Server A',
        sourceKey: 'server-a|source-a',
      );
      final secondEntry = createEntry(
        serverName: 'Server B',
        sourceKey: 'server-b|source-b',
      );

      final groups = groupVersionEntries([firstEntry, secondEntry]);

      expect(groups, hasLength(1));
      expect(groups.single.representative, same(firstEntry));
      expect(groups.single.members, [firstEntry, secondEntry]);
      expect(groups.single.serverNames, ['Server A', 'Server B']);
    });

    test('does not merge sources without a positive file size', () {
      final missingSizeEntry = createEntry(
        serverName: 'Server A',
        sourceKey: 'server-a|source-a',
        sizeBytes: null,
      );
      final zeroSizeEntry = createEntry(
        serverName: 'Server B',
        sourceKey: 'server-b|source-b',
        sizeBytes: 0,
      );

      final groups = groupVersionEntries([missingSizeEntry, zeroSizeEntry]);

      expect(groups, hasLength(2));
      expect(groups[0].members, [missingSizeEntry]);
      expect(groups[1].members, [zeroSizeEntry]);
    });

    test('keeps different resolution labels in separate groups', () {
      final ultraHdEntry = createEntry(
        serverName: 'Server A',
        sourceKey: 'server-a|source-a',
      );
      final fullHdEntry = createEntry(
        serverName: 'Server B',
        sourceKey: 'server-b|source-b',
        resolutionLabel: '1080P',
      );

      final groups = groupVersionEntries([ultraHdEntry, fullHdEntry]);

      expect(groups, hasLength(2));
    });

    test('does not merge duplicate files from the same server', () {
      final firstEntry = createEntry(
        serverName: 'Server A',
        sourceKey: 'server-a|source-a',
      );
      final secondEntry = createEntry(
        serverName: 'Server A',
        sourceKey: 'server-a|source-b',
      );

      final groups = groupVersionEntries([firstEntry, secondEntry]);

      expect(groups, hasLength(2));
    });

    test(
      'uses selected member as visible server without moving representative',
      () {
        final representative = createEntry(
          serverName: 'Server A',
          sourceKey: 'server-a|source-a',
        );
        final selectedMember = createEntry(
          serverName: 'Server B',
          sourceKey: 'server-b|source-b',
          selected: true,
        );

        final group = groupVersionEntries([
          representative,
          selectedMember,
        ]).single;

        expect(group.representative, same(representative));
        expect(group.activeMember, same(selectedMember));
        expect(group.displayData.serverName, 'Server B');
        expect(group.displayData.sourceKey, 'server-b|source-b');
        expect(group.displayData.selected, isTrue);
        expect(group.displayData.mergedServerNames, ['Server A', 'Server B']);
      },
    );

    test('propagates current state from any member to collapsed card', () {
      final representative = createEntry(
        serverName: 'Server A',
        sourceKey: 'server-a|source-a',
      );
      final currentMember = createEntry(
        serverName: 'Server B',
        sourceKey: 'server-b|source-b',
        isCurrent: true,
      );

      final group = groupVersionEntries([representative, currentMember]).single;

      expect(group.hasCurrentMember, isTrue);
      expect(group.displayData.isCurrent, isTrue);
      expect(group.displayData.serverName, 'Server B');
    });
  });
}
